【题目大意】
和平委员会每个党派有2个人,只能派出其中1个,其中有一些人之间互相讨厌不能同时派出。求出派遣方案,如果有多种方案输出字典序最小的方案。
【思路】
最小字典序只能用暴力染色。初始时均没有染色。枚举将党派第一个人染成红色,然后dfs把和它相连的全部染成红色,如果其中有的是蓝色那么矛盾;如果第一种情况矛盾那么dfs第二个人染成红色,如果也矛盾说明无解。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #define W 0 7 #define R 1 8 #define B 2 9 using namespace std; 10 const int MAXN=(8000+50)*2; 11 int n,m; 12 vector<int> E[MAXN]; 13 int col[MAXN],ans[MAXN],cnt; 14 15 void addedge(int u,int v) 16 { 17 E[u].push_back(v); 18 } 19 20 int dfs(int u) 21 { 22 col[u]=R; 23 col[u^1]=B; 24 ans[++cnt]=u; 25 for (int i=0;i<E[u].size();i++) 26 { 27 int v=E[u][i]; 28 if (col[v]==R) continue; 29 if (col[v]==B || !dfs(v)) return 0; 30 } 31 return 1; 32 } 33 34 void init() 35 { 36 for (int i=0;i<m;i++) 37 { 38 int u,v; 39 scanf("%d%d",&u,&v); 40 u--;v--; 41 addedge(u,v^1); 42 addedge(v,u^1); 43 } 44 } 45 46 int solve() 47 { 48 memset(col,0,sizeof(col)); 49 for (int i=0;i<n*2;i++) 50 if (!col[i]) 51 { 52 cnt=0; 53 if (!dfs(i)) 54 { 55 for (int j=1;j<=cnt;j++) col[ans[j]]=col[ans[j]^1]=W; 56 if (!dfs(i^1)) return 0; 57 } 58 } 59 return 1; 60 } 61 62 int main() 63 { 64 //freopen("spo0.in","r",stdin); 65 //freopen("spo0.out","w",stdout); 66 while (scanf("%d%d",&n,&m)!=EOF) 67 { 68 for (int i=0;i<2*n;i++) vector<int>().swap(E[i]);//不要忘记清空vector 69 init(); 70 if(solve()) 71 { 72 for(int i=0;i<2*n;i++) 73 { 74 if(col[i]==R) printf("%d\n", i+1); 75 } 76 } 77 else 78 { 79 printf("NIE\n"); 80 } 81 } 82 return 0; 83 }