POJ 2749 && HDU 1815 Building roads(2-SAT+二分)
来源:互联网 发布:nagios windows客户端 编辑:程序博客网 时间:2024/05/21 22:05
Desciption
给出n个牛棚、两个特殊点s1,s2的坐标。s1,s2直连。牛棚只能连s1或s2。还有,某些牛棚只能连在同一个s,某些牛棚不能连在同一个s。求使最远的牛棚间的最小距离(距离是曼哈顿距离)
Input
第一行包括三个整数n,A,B分别表示牛棚数量,需要连在不同s的牛棚对数需要连在相同s的牛棚对数,第二行四个整数表示s1,s2的坐标,之后A行每行两个整数a和b表示a牛棚与b牛棚需要连在不同s上,最后B行每行两个整数a和b表示a牛棚与b牛棚需要连在相同s上
Output
输出最远牛棚间的最短距离
Sample Input
4 1 1
12750 28546 15361 32055
6706 3887
10754 8166
12668 19380
15788 16059
3 4
2 3
Sample Output
53246
Solution
典型的2-sat判定。条件如下:
x hate y:x->~y,~y->x,~x->y,y->~x
x like y: x->y,y->x,~x->~y,~y->~x
二分最大距离mid,则有相应限制:
dis(i,s1)+dis(s1,j)>mid i->~j j->i
dis(i,s2)+dis(s2,j)>mid ~i->j ~j->i
dis(i,s1)+dis(s1,s2)+dist(s2,j)>mid i->j ~j->~i
dis(i,s2)+dis(s2,s1)+dist(s1,j)>mid ~i->~j j->i
对于每个确定的最大距离,只要构图后用tarjan算法求强联通分量并判断是否使得布尔公式值为真的一组布尔变量赋值,如果不存在则left右移,如果存在则right左移即可
Code
#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<stack>#include<vector>using namespace std;#define maxn 1111#define maxm 1111111#define INF 11111111 stack<int>st; int n,A,B,scc,index; int low[maxn],dfn[maxn],instack[maxn],fa[maxn]; struct node{ int x,y;};struct edge{ int to,next;};edge g[maxm];int head[maxm],tol;node s1,s2,cow[maxn];int hate[maxn][2],like[maxn][2];int dis(node a,node b)//求两点之间的曼哈顿距离 { return abs(a.x-b.x)+abs(a.y-b.y);}void init()//初始化 { tol=0; memset(head,-1,sizeof(head)); scc=index=0; while(!st.empty())st.pop(); memset(dfn,0,sizeof(dfn)); memset(instack,0,sizeof(instack)); memset(low,0,sizeof(low));} void add(int a,int b){ g[tol].to=b; g[tol].next=head[a]; head[a]=tol++; }void tarjan(int u)//求强联通分量 { dfn[u]=low[u]=++index; instack[u]=1; st.push(u); int v; for(int i=head[u];i!=-1;i=g[i].next) { v=g[i].to; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { scc++; do { v=st.top(); st.pop(); fa[v]=scc; instack[v]=0; }while(v!=u); } } bool check()//判断可行性 { for(int i=0;i<2*n;i++)//求强联通分量 if(!dfn[i]) tarjan(i); for(int i=0;i<2*n;i+=2) if(fa[i]==fa[i+1])//矛盾 return false; return true;}int dis1[maxn],dis2[maxn];int main(){ while(scanf("%d%d%d",&n,&A,&B)!=EOF) { scanf("%d%d%d%d",&s1.x,&s1.y,&s2.x,&s2.y); int len=dis(s1,s2); for(int i=0;i<n;i++) { scanf("%d%d",&cow[i].x,&cow[i].y); dis1[i]=dis(cow[i],s1); dis2[i]=dis(cow[i],s2); } for(int i=0;i<A;i++) { scanf("%d%d",&hate[i][0],&hate[i][1]); hate[i][0]--;hate[i][1]--; } for(int i=0;i<B;i++) { scanf("%d%d",&like[i][0],&like[i][1]); like[i][0]--;like[i][1]--; } int left=0,right=8000000,ans=-1; while(left<=right) { init();//初始化 for(int i=0;i<A;i++)//构图 { add(2*hate[i][0]+1,2*hate[i][1]); add(2*hate[i][0],2*hate[i][1]+1); add(2*hate[i][1]+1,2*hate[i][0]); add(2*hate[i][1],2*hate[i][0]+1); } for(int i=0;i<B;i++)//构图 { add(2*like[i][0],2*like[i][1]); add(2*like[i][0]+1,2*like[i][1]+1); add(2*like[i][1],2*like[i][0]); add(2*like[i][1]+1,2*like[i][0]+1); } int mid=(left+right)/2; for(int i=0;i<n;i++)//构图 for(int j=i+1;j<n;j++) { if(dis1[i]+dis1[j]>mid) { add(2*i,2*j+1); add(2*j,2*i+1); } if(dis2[i]+dis2[j]>mid) { add(2*i+1,2*j); add(2*j+1,2*i); } if(dis1[i]+dis2[j]+len>mid) { add(2*i,2*j); add(2*j+1,2*i+1); } if(dis2[i]+dis1[j]+len>mid) { add(2*i+1,2*j+1); add(2*j,2*i); } } if(check())//存在可行解 { ans=mid; right=mid-1; } else//不存在可行解 left=mid+1; } printf("%d\n",ans); } return 0;}
- POJ 2749 && HDU 1815 Building roads(2-SAT+二分)
- Poj 2749 & Hdu 1815 Building roads (2-SAT + 二分 建图)
- HDU 1815, POJ 2749 Building roads(2-sat)
- poj 2749 Building roads #二分+2-sat
- POJ 2749 - Building roads(2-SAT+二分)
- |poj 2749|2-SAT|二分|Building roads
- poj 2749 Building roads(2-sat+二分)
- poj 2749 Building roads (二分+拆点+2-sat)
- hdu 1815 Building roads(二分+2-sat判定)
- HDU 1815 Building roads(二分+2-SAT)
- poj 2749 & hdu 1815 Building roads(2-SAT + 二分,好题)
- POJ 2749 || HDU 1815 Building roads 2-sat
- POJ 2749 Building roads (2-SAT)
- POJ 2749|Building roads|2-SAT|二分答案
- Poj 2749 Building roads【二分+2-Sat----------Tarjan强连通】
- POJ--2749[Building roads] 2-SAT第五题,2—SAT+二分判定
- POJ 2749 Building roads (2-sat)
- POJ 2749 Building roads(2-SAT)
- 做嵌入式经典网站!(转)
- 乘积最大
- 解决 Boot Camp 虚拟机升级到 Windows 10 后 Parallels Desktop 不能识别的问题
- 使用core dump查看程序运行异常
- NSData NSDate NSString NSArray NSDictionary 相互转换
- POJ 2749 && HDU 1815 Building roads(2-SAT+二分)
- 经验分享:多屏复杂动画CSS技巧三则
- SQL 2014 SP1 附加数据库时“create file遇到操作系统错误5拒绝访问”
- 排序方法总和
- LA4255 Guess (拓扑排序)
- Android内存管理机制
- 如何使用会声会影X7添加视频字幕方法
- hdoj 5120 Intersection 【计算圆环相交面积】
- poj_2417 (baby_step,giant_step算法)