POJ3207 Ikki's Story IV - Panda's Trick
Ikki's Story IV - Panda's Trick
题目大意:一个圆,上面依次有n个点:0、1、2、3、……、n-1,给出m条边,每边连接其中的两个点,边可以从圆内连,也可以从圆外连,每个点最多只连一条边。问是否可以实现连边且每两条边都不相交?
————————————————————————————————————
每一条边只能从圆内连或圆外连,就是2-SAT问题。
如果两边的起点交叉,也就是u[i]<u[j]<v[i]<v[j]或者u[j]<u[i]<v[j]<v[i],那么两边只能一条从圆内连一条从圆外连,也就是
i*2---->j*2-1
j*2-1---->i*2
j*2---->i*2-1
i*2-1---->j*2
然后tarjan,求每个点的强连通分量,如果i*2和i*2-1在一个强连通分量内,也就是第i条边在圆内又在圆外,那么无解!否则有解!
————————————————————————————————————
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1005; 6 const int maxm=505; 7 int n,m; 8 int uu[maxm],vv[maxm]; 9 struct edge 10 { 11 int u,v,nxt; 12 }e[maxm*maxm*2]; 13 int head[maxm<<1],js; 14 void addage(int u,int v) 15 { 16 e[++js].u=u;e[js].v=v; 17 e[js].nxt=head[u];head[u]=js; 18 } 19 int low[maxm<<1],dfn[maxm<<1],cnt,st[maxm<<1],top,lt[maxm<<1],lts; 20 void tarjan(int u) 21 { 22 low[u]=dfn[u]=++cnt; 23 st[++top]=u; 24 for(int i=head[u];i;i=e[i].nxt) 25 { 26 int v=e[i].v; 27 if(!dfn[v]) 28 { 29 tarjan(v); 30 low[u]=min(low[u],low[v]); 31 } 32 else if(!lt[v]) low[u]=min(low[u],dfn[v]); 33 } 34 if(dfn[u]==low[u]) 35 { 36 lt[u]=++lts; 37 while(st[top]!=u)lt[st[top--]]=lts; 38 --top; 39 } 40 } 41 42 int main() 43 { 44 scanf("%d%d",&n,&m); 45 for(int i=1;i<=m;++i) 46 { 47 scanf("%d%d",uu+i,vv+i); 48 if(uu[i]>vv[i])swap(uu[i],vv[i]); 49 } 50 for(int i=1;i<=m;++i) 51 for(int j=i+1;j<=m;++j) 52 if((uu[i]<uu[j]&&uu[j]<vv[i]&&vv[i]<vv[j])||(uu[j]<uu[i]&&uu[i]<vv[j]&&vv[j]<vv[i])) 53 { 54 addage(i*2-1,j*2); 55 addage(j*2,i*2-1); 56 addage(i*2,j*2-1); 57 addage(j*2-1,i*2); 58 } 59 for(int i=1;i<=m*2;++i) 60 if(!dfn[i])tarjan(i); 61 for(int i=1;i<=m;++i) 62 if(lt[i*2]==lt[i*2-1]) 63 { 64 puts("the evil panda is lying again"); 65 return 0; 66 } 67 puts("panda is telling the truth..."); 68 return 0; 69 }