POJ 3207 2_sat
来源:互联网 发布:golang docker 编辑:程序博客网 时间:2024/05/16 06:35
//poj 3207 2_sat 第一题//为什么觉得和连通分量很像呢。。//扯蛋的题意:平面上有一个圆,圆的边上按顺时针放着0..n-1共n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接//,也可以从圆的外部连接。给你的信息中,每个点最多只能连一条边。问是否可以连接这m条边,使这些边都不相交。//把边看成2-sat,因为每一条边只有两种状态,在圆内和园外两种可能,这样就满足了2-sat状态了。每两条ab和cd边可能相交情况为://(c<a && a<d && d<b)|| (a<c && c<b && b<d)。内边:2*i,外边:2*i+1//POJ 3207//题意:平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,//比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。//给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,//使这些边都不相交。////思路:对于每条Link,要么在圆外,要么在圆内,且不可同时满足,//只能两者取一,判断这M条Link是否合法,也就是M条Link不冲突,//这就是典型的2-sat问题了。 将每条Link i 看做一个点,如果Link在圆内,//则选做i ,如果在圆外, 则选做i'。对于两条线(i,j) ,如果i,j不能同时//在圆内,也就可以推出两者不能同时在圆外,这个证明很容易,读者可//以自行证明。i, j不能同时在圆内,则有边(i, j') 、(j ,i')、(i',j)、(j' ,i)//(这是由2-sat的构图方式决定的,具体可以看《由对称性解2-SAT问题》// 这篇论文)。建图完了之后,本题就是判断2-sat问题是否有解,// 先求原图的强连通分量,并缩点,(这里我们称:(i,i')属于同一组),// 判断是否存在(i,i')属于同一组,若存在,则不可能,若不存在则可能。////最后看是不有有一对点在同一个连通分量//明明是传说中的2-sat,为什么我怎么看怎么像水题。。//一开始栈开得不够。。不过为什么/////我每条边建了4条边//双向边什么的要注意多建一点边过的代码。#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<algorithm>#include<string>#include<vector>#include<queue>#define maxn 1050using namespace std;///我每条边建了4条边struct Edge{ int from, to, nex; bool sign;//是否为桥}edge[60*maxn];int head[maxn], edgenum;void addedge(int u, int v){ Edge E={u, v, head[u], false}; edge[edgenum] = E; head[u] = edgenum++;}int DFN[maxn], Low[maxn], Stack[maxn], top, Time; //Low[u]是点集{u点及以u点为根的子树} 中(所有反向弧)能指向的(离根最近的祖先v) 的DFN[v]值(即v点时间戳)int taj;//连通分支标号,从1开始int Belong[maxn];//Belong[i] 表示i点属于的连通分支bool Instack[maxn];vector<int> bcc[maxn]; //标号从1开始void tarjan(int u ,int fa)//求出图的强联通分量{ DFN[u] = Low[u] = ++ Time ; Stack[top ++ ] = u ; Instack[u] = 1 ; for (int i = head[u] ; ~i ; i = edge[i].nex ){ int v = edge[i].to ; if(DFN[v] == -1) { tarjan(v , u) ; Low[u] = min(Low[u] ,Low[v]) ; if(DFN[u] < Low[v]) { edge[i].sign = 1;//为割桥 } } else if(Instack[v]) Low[u] = min(Low[u] ,DFN[v]) ; } if(Low[u] == DFN[u]){ int now; taj ++ ;bcc[taj].clear(); do{ now = Stack[-- top] ; Instack[now] = 0 ; Belong [now] = taj ; bcc[taj].push_back(now); }while(now != u) ; }}void tarjan_init(int all){ memset(DFN, -1, sizeof(DFN)); memset(Instack, 0, sizeof(Instack)); top = Time = taj = 0; for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i); //注意开始点标!!!}vector<int>G[maxn];void init(){memset(head, -1, sizeof(head)); edgenum=0;}int U[maxn],V[maxn];bool judge(int x,int y){ // cout<<"miao"<<endl; int a=U[x]; int b=V[x]; int c=U[y]; int d=V[y]; if((a<c && c<b && b<d) || (a<d && d<b && c<a)) return true; else return false;}int n,m;int main(){while(scanf("%d%d",&n,&m)!=EOF){ for(int i=1;i<=m;i++) { scanf("%d%d",&U[i],&V[i]); U[i]++;V[i]++; } init(); for(int i=1;i<m;i++) for(int j=i+1;j<=m;j++) { if(judge(i,j))///相交 { addedge(2*i-1,2*j); addedge(2*j,2*i-1); addedge(2*i,2*j-1); addedge(2*j-1,2*i); } } tarjan_init(m*2); bool flag=true; for(int i=1;i<=m;i++) { if(Belong[2*i-1]==Belong[2*i]) {flag=false;break;} } if(flag) cout<<"panda is telling the truth..."<<endl; else cout<<"the evil panda is lying again"<<endl;}}
0 0
- POJ 3207 2_sat
- poj 3648 Wedding 2_SAT
- poj 2723 Get Luffy Out 2_SAT
- poj 3683 Priest John's Busiest Day 2_sat
- 2_SAT问题
- HDU 3622 2_SAT
- 2_SAT问题小结
- hnoi2010 平面图判定 2_SAT
- ACM-ICPC wf2014 金属加工厂 metal 单调性维护+2_SAT
- pku3678 2_SAT现有N个数,每个数不是0就是1。现给出一些有关这些数的与,或,异或的关系,问可能不?
- 2-sat 五题 poj 3207 & poj 3683 & poj 3678 &poj 2723 & poj 2749
- POJ 3207 2-sat
- poj 3207 2-sat
- 【2-SAT】POJ 3207
- POJ 3207 2-SAT
- poj 3207 2-sat
- poj 3207 2-SAT
- POJ 3207 2-SAT
- DFS Unique Binary Search Trees II
- 怎样从10亿查询词找出出现频率最高的10个
- C++作业4.21
- 简单返回顶部代码及注释说明
- matlab 与c++混合编码 (matlab .m文件转为c++的dll文件)
- POJ 3207 2_sat
- android之JNI开发步骤总结
- spring mvc 的设计模式
- 关于javamail的一些笔记
- [转帖]易飞 ERP 9.05 注册机
- POJ 3241 曼哈顿最小生成树
- 调整逻辑卷(lv)大小和创建新的逻辑卷
- 如果在eclipse中,run as运行的时候,如果无法找着设备
- POJ 3621 最优比率环