现在的位置: 首页 > 综合 > 正文

hdu 1815,poj 2749 (2—SAT+二分)

2018年02月21日 ⁄ 综合 ⁄ 共 2302字 ⁄ 字号 评论关闭

每个牛棚跟一个中转站相连,求最小的任意两牛棚间的距离中的最大值

又是2—SAT+二分验证求最小的最大值,

2—SAT:如果a与b矛盾,建边a—>b‘;

枚举任意两牛棚之间的距离,如果大于最大距离,就要相反的方式连接,

刚开始没有考虑两个中转站的距离,结果一直不对,还以为算法有bug,郁闷了半天。

如果两牛棚连接在两个不同的中转站,两点间的距离要加上中转站的距离









#include<stdio.h>
#include<stack>
#include<string.h>
#define N 2000
#define M 1000
using namespace std;
struct edage
{
	int ed;
	int next;
}E[M*M];
struct op
{
	int x,y;
}P[N],P0,P1;
int n,low[N],dfs[N],ins[N],map[N*2],idx,ans,first[N],rfirst[N],belong[N],num,rnum,len;
stack<int>Q;
void addeage(int x,int y)
{
	E[num].ed=y;
	E[num].next=first[x];
	first[x]=num++;
}
int dis(op a,op b)
{
	return abs(a.x-b.x)+abs(a.y-b.y);
}
void Tarjan(int x)
{
	int p,v;
	low[x]=dfs[x]=idx++;
	ins[x]=1;
	Q.push(x);
	for(p=first[x];p!=-1;p=E[p].next)
	{
		v=E[p].ed;
		if(dfs[v]==-1)
		{
			Tarjan(v);
			low[x]=low[x]>low[v]?low[v]:low[x];
		}
		else if(ins[v]==1)
		{
			low[x]=low[x]>dfs[v]?dfs[v]:low[x];
		}
	}
	if(dfs[x]==low[x])
	{
		do
		{
			v=Q.top();
			Q.pop();
			ins[v]=0;
			belong[v]=ans;
		}while(v!=x);
		ans++;
	}
}
int sum=0;
int judge(int d,int min,int max)
{
	int i,j;
	memcpy(first,rfirst,sizeof(first));
	num=rnum;
	for(i=1;i<=n;i++)//枚举两点之间的距离
		for(j=i+1;j<=n;j++)
		{
			if(map[i]+map[j]>d)//连接相同同中转站不符合
			{
				addeage(i,j+n);
				addeage(j,i+n);
			}
			if(map[i]+map[j+n]+len>d)//连接不同的中转站不符合
			{
				addeage(i,j);
				addeage(j+n,i+n);
			}
			if(map[i+n]+map[j]+len>d)//连接不同的中转站不符合
			{
				addeage(i+n,j+n);
				addeage(j,i);
			}
			if(map[i+n]+map[j+n]>d)//连接相同同中转站不符合
			{
				addeage(i+n,j);
				addeage(j+n,i);
			}
		}
		memset(low,0,sizeof(low));
		memset(ins,0,sizeof(ins));
		memset(dfs,-1,sizeof(dfs));
		memset(belong,0,sizeof(belong));
		idx=ans=1;
		for(i=1;i<=n*2;i++)
		{
			if(dfs[i]==-1)
				Tarjan(i);
		}
		for(i=1;i<=n;i++)
			if(belong[i]==belong[i+n])
				return 0;
			return 1;
}
int main()
{
	int i,m,k,min,max,mid,flag,x,y,mmax;
	while(scanf("%d%d%d",&n,&m,&k)!=-1)
	{
		memset(first,-1,sizeof(first));
		num=0;
		scanf("%d%d%d%d",&P0.x,&P0.y,&P1.x,&P1.y);
		for(i=1;i<=n;i++)
			scanf("%d%d",&P[i].x,&P[i].y);
		min=999999999;
		max=-1;
		for(i=1;i<=n;i++)
		{
           map[i]=dis(P[i],P0);
		   map[i+n]=dis(P[i],P1);
		   if(min>map[i])
			   min=map[i];
		   if(min>map[i+n])
			   min=map[i+n];
		   if(max<map[i])
			   max=map[i];
		   if(max<map[i+n])
			   max=map[i+n];
		}
		len=dis(P0,P1);
		for(i=0;i<m;i++)
		{
			scanf("%d%d",&x,&y);
			addeage(x,y+n);
			addeage(y,x+n);
			addeage(x+n,y);
			addeage(y+n,x);
		}
		for(i=0;i<k;i++)
		{
			scanf("%d%d",&x,&y);
			addeage(x,y);
			addeage(x+n,y+n);
			addeage(y,x);
			addeage(y+n,x+n);
		}
		memcpy(rfirst,first,sizeof(first));
		rnum=num;
		 min=min*2,max=max*2+len;
		mmax=-1;flag=0;
		while(min<=max)
		{
			mid=(min+max)/2;
			if(judge(mid,min,max))
			{
				max=mid-1;
					mmax=mid;
			}
			else min=mid+1;
		}
		printf("%d\n",mmax);
	}
	return 0;
}







抱歉!评论已关闭.