hdu 4751 Divide Groups(dfs染色 或 2-sat)
Problem Description
![](http://acm.hdu.edu.cn/data/images/C479-1004-1.jpg)
Input
The input contains several test cases, terminated by EOF. Each case starts with a positive integer n (2<=n<=100), which means the number of people joining in the event. N lines follow. The i-th line contains some integers which are the id of students that the i-th student knows, terminated by 0. And the id starts from 1.
Output
If divided successfully, please output "YES" in a line, else output "NO".
Sample Input
3
3 0
1 0
1 2 0
Sample Output
YES
Source
怒贴两种方法的代码,以表示我的愤怒,这么简单的题目都想的那么复杂
第一种是dfs染色法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<math.h> 7 #include<algorithm> 8 #include<queue> 9 #include<set> 10 #include<bitset> 11 #include<map> 12 #include<vector> 13 #include<stdlib.h> 14 using namespace std; 15 #define ll long long 16 #define eps 1e-10 17 #define MOD 1000000007 18 #define N 106 19 #define inf 1e12 20 int n; 21 vector<int>v[N]; 22 int color[N]; 23 int mp[N][N]; 24 bool dfs(int u,int c){ 25 color[u]=c; 26 for(int i=0;i<v[u].size();i++){ 27 int num=v[u][i]; 28 if(color[num]!=-1){ 29 if(color[num]==c){ 30 return false; 31 } 32 continue; 33 } 34 if(!dfs(num,!c)) return false; 35 } 36 return true; 37 } 38 int main() 39 { 40 while(scanf("%d",&n)==1){ 41 for(int i=0;i<N;i++){ 42 v[i].clear(); 43 } 44 memset(mp,0,sizeof(mp)); 45 for(int i=1;i<=n;i++){ 46 int x; 47 scanf("%d",&x); 48 while(x!=0){ 49 //v[i].push_back(x); 50 //v[x].push_back(i); 51 mp[i][x]=1; 52 scanf("%d",&x); 53 } 54 } 55 56 for(int i=1;i<=n;i++){ 57 for(int j=i+1;j<=n;j++){ 58 if(mp[i][j]==0 || mp[j][i]==0){ 59 v[i].push_back(j); 60 v[j].push_back(i); 61 } 62 } 63 } 64 65 memset(color,-1,sizeof(color)); 66 int flag=1; 67 for(int i=1;i<=n;i++){ 68 if(color[i]==-1 && !dfs(i,0)){ 69 flag=0; 70 break; 71 } 72 } 73 if(flag){ 74 printf("YES\n"); 75 } 76 else{ 77 printf("NO\n"); 78 } 79 } 80 return 0; 81 }
第二种是2-sat,其实本质上和上一种是一样的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<math.h> 7 #include<algorithm> 8 #include<queue> 9 #include<set> 10 #include<bitset> 11 #include<map> 12 #include<vector> 13 #include<stdlib.h> 14 #include <stack> 15 using namespace std; 16 #define PI acos(-1.0) 17 #define max(a,b) (a) > (b) ? (a) : (b) 18 #define min(a,b) (a) < (b) ? (a) : (b) 19 #define ll long long 20 #define eps 1e-10 21 #define MOD 1000000007 22 #define N 106 23 #define inf 1e12 24 int n,m; 25 26 int mp[N][N]; 27 int tot; 28 int head[N]; 29 int vis[N]; 30 int tt; 31 int scc; 32 stack<int>s; 33 int dfn[N],low[N]; 34 int col[N]; 35 struct Node 36 { 37 int from; 38 int to; 39 int next; 40 }edge[N*N]; 41 void init() 42 { 43 tot=0; 44 scc=0; 45 tt=0; 46 memset(head,-1,sizeof(head)); 47 memset(dfn,-1,sizeof(dfn)); 48 memset(low,0,sizeof(low)); 49 memset(vis,0,sizeof(vis)); 50 memset(col,0,sizeof(col)); 51 } 52 void add(int s,int u)//邻接矩阵函数 53 { 54 edge[tot].from=s; 55 edge[tot].to=u; 56 edge[tot].next=head[s]; 57 head[s]=tot++; 58 } 59 void tarjan(int u)//tarjan算法找出图中的所有强连通分支 60 { 61 dfn[u] = low[u]= ++tt; 62 vis[u]=1; 63 s.push(u); 64 int cnt=0; 65 for(int i=head[u];i!=-1;i=edge[i].next) 66 { 67 int v=edge[i].to; 68 if(dfn[v]==-1) 69 { 70 // sum++; 71 tarjan(v); 72 low[u]=min(low[u],low[v]); 73 } 74 else if(vis[v]==1) 75 low[u]=min(low[u],dfn[v]); 76 } 77 if(dfn[u]==low[u]) 78 { 79 int x; 80 scc++; 81 do{ 82 x=s.top(); 83 s.pop(); 84 col[x]=scc; 85 vis[x]=0; 86 }while(x!=u); 87 } 88 } 89 bool two_sat(){ 90 91 for(int i=0;i<2*n;i++){ 92 if(dfn[i]==-1){ 93 tarjan(i); 94 } 95 } 96 for(int i=0;i<n;i++){ 97 if(col[2*i]==col[2*i+1]){ 98 return false; 99 } 100 } 101 return true; 102 } 103 int main() 104 { 105 while(scanf("%d",&n)==1){ 106 init(); 107 memset(mp,0,sizeof(mp)); 108 109 while(!s.empty()){ 110 s.pop(); 111 } 112 int a,b,c; 113 int x; 114 for(int i=0;i<n;i++){ 115 scanf("%d",&x); 116 while(x!=0){ 117 x--; 118 mp[i][x]=1; 119 scanf("%d",&x); 120 } 121 } 122 for(int i=0;i<n;i++){ 123 for(int j=0;j<n;j++){ 124 if(i==j) continue; 125 if(mp[i][j]==0){ 126 add(2*i,2*j+1); 127 add(2*j,2*i+1); 128 add(2*i+1,2*j); 129 add(2*j+1,2*i); 130 } 131 } 132 } 133 if(two_sat()){ 134 printf("YES\n"); 135 } 136 else{ 137 printf("NO\n"); 138 } 139 } 140 return 0; 141 }