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
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
否则输出 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 }