-
【2-SAT(最小字典序/暴力染色)】HDU1814-Peaceful Commission
- 题意:
- 和平委员会每个党派有2个人,只能派出其中1个,其中有一些人之间互相讨厌不能同时派出。求出派遣方案,如果有多种方案输出字典序最小的方案。
- 思路:
- 最小字典序只能用暴力染色。初始时均没有染色。枚举将党派第一个人染成红色,然后dfs把和它相连的全部染成红色,如果其中有的是蓝色那么矛盾;如果第一种情况矛盾那么dfs第二个人染成红色,如果也矛盾说明无解
- 注意是相互冲突的两个人 u,v 那么 对 u v’ v u’ 进行建立有向边
-
#include<bits/stdc++.h> using namespace std; #define maxn 50000 int n,m,a,b,col[maxn]; int cnt,head[maxn],id,stk[maxn]; struct node { int v,to; } edge[maxn]; void add(int x,int y) { edge[++cnt].v=y; edge[cnt].to=head[x]; head[x]=cnt; } bool dfs(int u) { col[u]=1; col[u^1]=2; stk[++id]=u; for(int i=head[u]; i!=-1; i=edge[i].to) { int v=edge[i].v; if(col[v]==1)continue; if(col[v]==2||!dfs(v))return 0; } return 1; } bool solve() { for(int i=0; i<2*n; i++) if(col[i]==0) { id=0; if(!dfs(i)) { for(int j=1; j<=id; j++)col[stk[j]]=col[stk[j]^1]=0; if(!dfs(i^1))return 0; } } return 1; } int main() { while(~scanf("%d%d",&n,&m)) { memset(head,-1,sizeof(head)); memset(col,0,sizeof(col)); cnt=0; while(m--) { scanf("%d%d",&a,&b); a--; b--; add(a,b^1); add(b,a^1); } if(solve()) { for(int i=0; i<2*n; i++) if(col[i]==1)printf("%d\n",i+1); } else printf("NIE\n"); } return 0; }