2016ACM/ICPC亞洲區大連站-重現賽 A
阿新 • • 發佈:2018-11-19
題目大意:
已知有n個人,他們進行了m場比賽,已知其中有X個好人,Y個壞人。比賽一定是在好人和壞人之間進行的。問是否能夠把n個人劃分成好人和壞人兩個部分
好人和中立人打 中立人變成壞人,壞人和中立人打 中立人變成好人
做的時候開始發現就是一個二分圖,開始不知道這種方法叫做染色法現在明白了
我們需要進行一下dfs 每次對一個好人搜尋後 也需要對他的對手進行搜尋,如果對手是不同陣營 繼續 ,是同陣營代表出錯,如果未被染色,就染上對立顏色,如果兩個中立人打的話,就對其中隨機一個人染一下色就好了,如果到最後還沒有人被染色,就代表沒法完全構成一個二分圖
以下為AC程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn = 5000; vector<int>g[maxn]; int flag[maxn]; int ans; int n,m,a,b; void init() { for(int i=1; i<=n; i++) { g[i].clear(); } memset(flag, 0, sizeof(flag)); ans=1; } void dfs(int u,int pre,int k) { if(!ans) return; flag[u]=k; for(int i=0; i<g[u].size(); i++) { int v=g[u][i]; if(v==pre) continue; if(k==1) { if(flag[v]==1) { ans=0; return ; } if(flag[v]==0) dfs(v,u,-1); } else { if(flag[v]==-1) { ans=0; return; } if(flag[v]==0) dfs(v,u,1); } } } int main() { while(~scanf("%d%d%d%d",&n,&m,&a,&b)) { init(); for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); g[a].push_back(b); g[b].push_back(a); } for(int i=1;i<=a;i++) { int temp; scanf("%d",&temp); flag[temp]=1; } for(int i=1;i<=b;i++) { int temp; scanf("%d",&temp); flag[temp]=-1; } for(int i=1;i<=n;i++) { if(flag[i]!=0) { dfs(i,0,flag[i]); } } for(int i=1;i<=n;i++) { if(flag[i]==0&&g[i].size()!=0) { dfs(i,0,1); } } for(int i=1;i<=n;i++) { if(flag[i]==0) { ans = 0; break; } } if(ans) printf("YES\n"); else printf("NO\n"); } return 0; }