poj 3207 2-SAT(圆周点连边不相交)

来源:互联网 发布:淘宝购买儿童戒指 编辑:程序博客网 时间:2024/05/17 22:47

题意:圆周上有n个点,标号为0-n-1。以这些点为顶点欲连m条边,其中每个顶点最多引出1条边。边可以在圆中也可以在圆外。问使得所有边不相交的连边方法是否存在?

思路:2-SAT。任意两条线如果在圆内相交,在圆外也必定相交,所以它们只能一个圆内一个圆外。以此建图tarjan之。边i在圆内用i表示,圆外用i+m表示。

#include <stdio.h>#include <string.h>#define max(a,b) ((a)>(b)?(a):(b))#define min(a,b) ((a)<(b)?(a):(b))#define N 1100struct edge{int y,next;}e[501*501*4];struct link{int x,y;}link[N];int n,m,component,top,tops,id;int first[N],dfn[N],low[N],stack[N],strong[N];void init(){tops = -1;top = component = id = 0;memset(first,-1,sizeof(first));memset(dfn,-1,sizeof(dfn));memset(strong,0,sizeof(strong));}void add(int x,int y){e[top].y = y;e[top].next = first[x];first[x] = top++;}int test_cross(int i,int j){int num=0,k;int x1 = link[i].x;int y1 = link[i].y;int x2 = link[j].x;int y2 = link[j].y;for(k = min(x1,y1)+1;k<max(x1,y1);k++){//两对点交替排列则num值必为1if(k==x2 || k==y2)num++;}return num==1;}void tarjan(int x){int i,y;dfn[x] = low[x] = ++id;stack[++tops] = x;for(i = first[x];i!=-1;i=e[i].next){y = e[i].y;if(dfn[y] == -1){tarjan(y);low[x] = min(low[x],low[y]);}else if(!strong[y])low[x] = min(low[x],dfn[y]);}if(dfn[x] == low[x]){component++;do{strong[stack[tops]] = component;}while(stack[tops--] != x);}}int main(){int i,j;freopen("a.txt","r",stdin);init();scanf("%d %d",&n,&m);for(i = 1;i<=m;i++)scanf("%d %d",&link[i].x,&link[i].y);for(i = 1;i<m;i++)for(j = i+1;j<=m;j++)if(test_cross(i,j)){add(i,j+m);add(j,i+m);add(i+m,j);add(j+m,i);}for(i = 1;i<=2*m;i++)if(dfn[i] == -1)tarjan(i);for(i = 1;i<=m;i++)if(strong[i] && (strong[i] == strong[i+m]))break;if(i > m)printf("panda is telling the truth...\n");elseprintf("the evil panda is lying again\n");return 0;}


0 0
原创粉丝点击