首页 > 代码库 > Party

Party

hdu3062:http://acm.hdu.edu.cn/showproblem.php?pid=3062

题意:中文题。

题解:很明显的2-sat。然后要深刻理解命题和逆否命题。如这一题,c1,c2,表示矛盾。则可以推出如果选c1,则要选~c2,逆否就是不选~c2就要选~c1,就是选c2和~c1,所以既可以加边了,然后就是2-sat。

  1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 #include<algorithm>  5 #include<vector>  6 using namespace std;  7 const int N=20002;  8 const int M=4000002;  9 struct Node{ 10   int u; 11   int v; 12 }e[N*2]; 13 struct Edge{ 14     int to,next; 15 } edge[M]; 16  17 int  n,m,cnt,dep,top,atype; 18 int  dfn[N],low[N],vis[N],head[N],st[N],belong[N],in[N],out[N],sum[N]; 19 //sum[i]记录第i个连通图的点的个数,in[i],out[i],表示缩点之后点的入度和初度。 20 void init(){ 21       cnt=dep=top=atype=0; 22     memset(head,-1,sizeof(head)); 23     memset(dfn,0,sizeof(dfn)); 24     memset(low,0,sizeof(low)); 25     memset(vis,0,sizeof(vis)); 26     memset(belong,0,sizeof(belong)); 27     memset(in,0,sizeof(in)); 28     memset(out,0,sizeof(out)); 29     memset(sum,0,sizeof(sum)); 30 } 31 void addedge(int u,int v){ 32     edge[cnt].to=v; 33     edge[cnt].next=head[u]; 34     head[u]=cnt++; 35 } 36  37 void Tarjan(int u){ 38     dfn[u]=low[u]=++dep; 39     st[top++]=u; 40     vis[u]=1; 41     for(int i=head[u]; i!=-1; i=edge[i].next){ 42         int v=edge[i].to; 43         if(!dfn[v]){ 44             Tarjan(v); 45             low[u]=min(low[u],low[v]); 46         } 47         else if(vis[v]){ 48             low[u]=min(low[u],dfn[v]); 49         } 50     } 51     int j; 52     if(dfn[u]==low[u]){ 53         atype++; 54         do{ 55             j=st[--top]; 56             belong[j]=atype; 57             sum[atype]++;   //记录每个连通分量中点的个数 58             vis[j]=0; 59         } 60         while(u!=j); 61     } 62 } 63 int main(){ 64    while(~scanf("%d%d",&n,&m)){ 65        init(); 66        for(int i=1;i<=m;i++){ 67          int a1,a2,c1,c2;a1++,a2++; 68             scanf("%d%d%d%d",&a1,&a2,&c1,&c2); 69              a1++;a2++; 70             if(c1==0&&c2==0){ 71                 addedge(a1,a2+n); 72                 addedge(a2,a1+n); 73             } 74             if(c1==0&&c2==1){ 75                 addedge(a1,a2); 76                 addedge(a2+n,a1+n); 77             } 78             if(c1==1&&c2==0){ 79                 addedge(a1+n,a2+n); 80                 addedge(a2,a1); 81             } 82             if(c1==1&&c2==1){ 83                 addedge(a1+n,a2); 84                 addedge(a2+n,a1); 85             } 86        } 87        for(int i=1;i<=n*2;i++) 88           if(!dfn[i])Tarjan(i); 89          bool flag=false; 90          for(int i=1;i<=n;i++){ 91             if(belong[i]==belong[i*2]){ 92                 flag=true; 93             } 94          } 95          if(!flag){ 96             printf("YES\n"); 97          } 98          else 99            printf("NO\n");100    }101 }
View Code

 

Party