POJ 2749 2SAT判定+二分
来源:互联网 发布:sql视图的作用 编辑:程序博客网 时间:2024/06/05 18:29
题意:图上n个点,使每个点都与俩个中转点的其中一个相连(二选一,典型2-sat),并使任意两点最大
距离最小(最大最小,2分答案),有些点相互hata,不能选同一个中转点,有些点相互LOVE,必需选相同中转点
(显然是2sat条件)。
关键:每次二分枚举limit,按limit建图,需要注意的是每条逻辑语句对应两条边(相互对称,逻辑上互为假言易位),
如:必需连通一个点,逻辑语句俩条:a->b,b->a,对应各自假言易位式,4条边。
距离最小(最大最小,2分答案),有些点相互hata,不能选同一个中转点,有些点相互LOVE,必需选相同中转点
(显然是2sat条件)。
关键:每次二分枚举limit,按limit建图,需要注意的是每条逻辑语句对应两条边(相互对称,逻辑上互为假言易位),
如:必需连通一个点,逻辑语句俩条:a->b,b->a,对应各自假言易位式,4条边。
相信二sat不再是问题了。
#include<iostream>//1200ms/2000ms 1A#include<queue>#include<stack>#include<cstdio>#include<cstring>#include<cmath>#include<vector>using namespace std;struct point{ int x,y;};vector<vector<int> >e(1050); int n,a,b;point s1,s2; int maxdis=4000001;point po[505]; point hate[1005]; point love[1005];int absint(int x) { if(x<0)return -x; return x;}int dis(point aa,point bb) //距离{ return absint(aa.x-bb.x)+absint(aa.y-bb.y);}void build(int limit) //每次二分后建图{ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) //注意不要加ELSE { if(i==j)continue; if((dis(po[i],s1)+dis(po[j],s2)+dis(s1,s2))>limit) //无法到达了, { e[2*i-1].push_back(2*j-1); e[2*j-2].push_back(2*i-2); } if((dis(po[i],s1)+dis(po[j],s1))>limit) { e[2*i-1].push_back(2*j-2); e[2*j-1].push_back(2*i-2); } if((dis(po[i],s2)+dis(po[j],s2))>limit) { e[2*i-2].push_back(2*j-1); e[2*j-2].push_back(2*i-1); } } for(int i=0;i<a;i++) //相互憎恨的 { e[hate[i].x*2-1].push_back(hate[i].y*2-2); e[hate[i].y*2-1].push_back(hate[i].x*2-2); e[hate[i].x*2-2].push_back(hate[i].y*2-1); e[hate[i].y*2-2].push_back(hate[i].x*2-1); } for(int i=0;i<b;i++) //相互喜爱的 { e[love[i].x*2-1].push_back(love[i].y*2-1); e[love[i].y*2-2].push_back(love[i].x*2-2); e[love[i].y*2-1].push_back(love[i].x*2-1); e[love[i].x*2-2].push_back(love[i].y*2-2); }}int vis[1050];int dfn[1050];int low[1050];bool instack[1050];int block[1050];int times=0; stack<int>s; int num=0;void tarjan(int u) //下边是2sat缩点判断可行{ dfn[u]=low[u]=++times; instack[u]=1; s.push(u); int len=e[u].size(); for(int i=0;i<len;i++) { int v=e[u][i]; if(!vis[v]) { vis[v]=1; tarjan(v); if(low[u]>low[v])low[u]=low[v]; } else if(instack[v]&&dfn[v]<low[u]) low[u]=dfn[v]; } if(dfn[u]==low[u]) { num++; int cur; do{ cur=s.top();s.pop(); instack[cur]=0; block[cur]=num; }while(cur!=u); }}bool check(int limit){ for(int i=0;i<=2*n-1;i++) { e[i].clear(); block[i]=vis[i]=dfn[i]=low[i]=instack[i]=0; } num=times=0; build(limit); for(int i=0;i<=2*n-1;i++) if(!vis[i]) { vis[i]=1; tarjan(i); } for(int i=0;i<=2*n-1;i+=2) if(block[i]==block[i+1]) return 0; return 1;}int main(){ scanf("%d%d%d",&n,&a,&b);scanf("%d%d%d%d",&s1.x,&s1.y,&s2.x,&s2.y); for(int i=1;i<=n;i++) scanf("%d%d",&po[i].x,&po[i].y); for(int i=0;i<a;i++) scanf("%d%d",&hate[i].x,&hate[i].y); for(int i=0;i<b;i++) scanf("%d%d",&love[i].x,&love[i].y); int right=maxdis,left=0,mid; if(!check(maxdis)){printf("-1\n");return 0;} while(right>left+1) { mid=(right+left)/2; if(check(mid)) { right=mid; } else left=mid; } if(check(right-1))printf("%d\n",right-1); else printf("%d\n",right); return 0;}
0 0
- POJ 2749 二分+2-sat判定
- POJ 2749 2SAT判定+二分
- POJ 2723 二分+ 2-sat 判定
- poj 2723 二分+2-sat判定
- POJ--2749[Building roads] 2-SAT第五题,2—SAT+二分判定
- poj 2749 Building roads s-SAT判定+二分
- poj 2296 Map Labeler(二分+2-sat判定)
- POJ 2296 Map Labeler ( 2-SAT判定 + 二分查找 )
- 【2-SAT+二分】POJ 2749
- COJ 1253 二分+2-sat判定
- ZOJ 3717 二分+2-sat判定。
- poj 2749 Building roads #二分+2-sat
- POJ 2749 - Building roads(2-SAT+二分)
- |poj 2749|2-SAT|二分|Building roads
- poj 2723【2-SAT+二分】
- poj 2296 二分+2-sat
- HDOJ 3715 Go Deeper (2Sat: 二分答案判定)
- hdu 3622 Bomb Game(二分+2-sat判定)
- ubuntu10.04.04系统 设置root用户默认登录用户,并设定成无需密码认证自动登录
- 腾讯马拉松之 湫湫系列故事——消灭兔子
- ovs-vsctl add-port br0 eth1 实际做了什么?
- C语言经典算法100例-005-三个数,从小到大输出
- NSCAssert 的使用
- POJ 2749 2SAT判定+二分
- LL(1)文法
- Git之忽略文件(ignore file)
- PopStar(消灭星星)游戏源代码下载、分析及跨平台移植---第一篇(界面)
- 利用Xcode自动生成文档
- Visual Studio 调试功能(四)
- PLMN概念和应用设置
- SLIC segmentation algorithm
- 姑且叫他【退役贴】(by csy)