hdu 3062 Party 2-SAT

题目链接:HDU - 3062

有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?
Input
n: 表示有n对夫妻被邀请 (n<= 1000)
m: 表示有m 对矛盾关系 ( m < (n - 1) * (n -1))
在接下来的m行中,每行会有4个数字,分别是 A1,A2,C1,C2
A1,A2分别表示是夫妻的编号
C1,C2 表示是妻子还是丈夫 ,0表示妻子 ,1是丈夫
夫妻编号从 0 到 n -1
Output
如果存在一种情况 则输出YES
否则输出 NO 
题目描述:中文题目,如上所述。
算法分析:2-SAT的入门题,如果u和v有矛盾,选u的同时必须选v^1,选v的同时只能选择u^1,然后缩点判断即可。
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<vector>
  9 #include<stack>
 10 using namespace std;
 11 const int maxn=2000+10;
 12 const int M=1000000+10;
 13 
 14 int n,m;
 15 struct node
 16 {
 17     int v,next;
 18 }edge[M*4];
 19 int head[maxn],edgenum;
 20 int dfn[maxn],low[maxn],scc[maxn],ind[maxn],vis[maxn];
 21 stack<int> S;
 22 int color[maxn],f[maxn];
 23 int dfs_clock,scc_cnt;
 24 vector<int> dag[maxn];
 25 void add(int u,int v)
 26 {
 27     edge[edgenum].v=v ;edge[edgenum].next=head[u] ;
 28     head[u]=edgenum++;
 29 }
 30 void init()
 31 {
 32     memset(head,-1,sizeof(head));
 33     memset(vis,0,sizeof(vis));
 34     memset(dfn,0,sizeof(dfn));
 35     memset(ind,0,sizeof(ind));
 36     memset(color,0,sizeof(color));
 37     edgenum=dfs_clock=scc_cnt=0;
 38 }
 39 void tarjan(int u)
 40 {
 41     dfn[u]=low[u]= ++dfs_clock;
 42     vis[u]=1;
 43     S.push(u);
 44     for (int i=head[u] ;i!=-1 ;i=edge[i].next)
 45     {
 46         int v=edge[i].v;
 47         if (!dfn[v])
 48         {
 49             tarjan(v);
 50             low[u]=min(low[u],low[v]);
 51         }
 52         else if (vis[v])
 53             low[u]=min(low[u],dfn[v]);
 54     }
 55     if (low[u]==dfn[u])
 56     {
 57         scc_cnt++;
 58         while (true)
 59         {
 60             int v=S.top() ;S.pop() ;
 61             vis[v]=0;
 62             scc[v]=scc_cnt;
 63             if (u==v) break;
 64         }
 65     }
 66 }
 67 void buildDag(int n)
 68 {
 69     for (int u=0 ;u<2*n ;u++)
 70     {
 71         for (int i=head[u] ;i!=-1 ;i=edge[i].next)
 72         {
 73             int v=edge[i].v;
 74             if (scc[v] != scc[u])
 75             {
 76                 dag[scc[v]].push_back(scc[u]);
 77                 ind[scc[u]]++;
 78             }
 79         }
 80     }
 81 }
 82 void topsort()
 83 {
 84     queue<int> Q;
 85     for (int i=1 ;i<=scc_cnt ;i++) if (!ind[i]) Q.push(i);
 86     while (!Q.empty())
 87     {
 88         int u=Q.front() ;Q.pop();
 89         if (!color[u]) color[u]=1,color[f[u]]=2;
 90         for (int i=0 ;i<(int)dag[u].size() ;i++)
 91         {
 92             int v=dag[u][i];
 93             ind[v]--;
 94             if (!ind[v]) Q.push(v);
 95         }
 96     }
 97 }
 98 void solve(int n)
 99 {
100     int flag=0;
101     for (int i=0 ;i<2*n ;i++) if (!dfn[i]) tarjan(i);
102     for (int i=0 ;i<n ;i++)
103     {
104         if(scc[2*i]==scc[(2*i)^1])
105         {
106             printf("NO\n");
107             flag=1;
108             return ;
109         }
110         //else f[scc[i]]=scc[i+1],f[scc[i+1]]=scc[i];
111     }
112     if (!flag) printf("YES\n");
113 //    for (int i=0 ;i<=scc_cnt ;i++) dag[i].clear();
114 //    buildDag(n);
115 //    topsort();
116     return ;
117 }
118 int main()
119 {
120     while (scanf("%d%d",&n,&m)!=EOF)
121     {
122         init();
123         int a,b,c,d;
124         for (int i=0 ;i<m ;i++)
125         {
126             scanf("%d%d%d%d",&a,&b,&c,&d);
127             int u=2*a+c,v=2*b+d;
128             add(u,v^1) ;add(v,u^1);
129         }
130         solve(n);
131     }
132     return 0;
133 }

 

posted @ 2015-04-15 10:29  huangxf  阅读(228)  评论(0编辑  收藏  举报