原文链接http://www.cnblogs.com/zhouzhendong/p/8099115.html
题目传送门 - HDU1814
题面
Description
根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立。不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍。
此委员会必须满足下列条件:
每个党派都在委员会中恰有1个代表,
如果2个代表彼此厌恶,则他们不能都属于委员会。
每个党在议会中有2个代表。代表从1编号到2n。 编号为2i-1和2i的代表属于第i个党派。
任务:写一程序读入党派的数量和关系不友好的代表对,计算决定建立和平委员会是否可能,若行,则列出委员会的成员表。
Input
输入文件的第一个行有2非负整数n和m。 他们各自表示:党派的数量n,1 <=n <=8000和不友好的代表对m,0 <=m <=20000。 在下面m行的每行为一对整数a,b,1<=a<b<=2n,中间用单个空格隔开。 它们表示代表a,b互相厌恶。
Output
如果委员会不能创立,则输出信息“NIE”。若能够成立,则输出包括n个从区间1到2n选出的整数,按升序写出,每行一个,这些数字为委员会中代表的编号。如果委员会能以多种方法形成,程序可以只写他们的某一个。
Sample Input
3 2
1 3
2 4
Sample Output
1
4
5
题解
第一道2-sat。
挖坑待填。
代码
#include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=8005*2,M=20005*2; struct Gragh{ int cnt,y[M],nxt[M],fst[N]; void clear(){ cnt=0; memset(fst,0,sizeof fst); } void add(int a,int b){ y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt; } }g; int n,m; int st[N],top,vis[N]; int opp(int x){ return x+(x%2==0?-1:1); } bool dfs(int x){ if (vis[opp(x)]) return 0; if (vis[x]) return 1; vis[x]=1; st[++top]=x; for (int i=g.fst[x];i;i=g.nxt[i]) if (!dfs(g.y[i])) return 0; return 1; } bool Two_sat(int n){ memset(vis,0,sizeof vis); for (int i=1;i<=n;i+=2){ if (vis[i]||vis[opp(i)]) continue; top=0; if (!dfs(i)){ while (top) vis[st[top--]]=0; if (!dfs(opp(i))) return 0; } } return 1; } int main(){ while (~scanf("%d%d",&n,&m)){ g.clear(); for (int i=1,a,b;i<=m;i++){ scanf("%d%d",&a,&b); g.add(a,opp(b)); g.add(b,opp(a)); } if (Two_sat(n*2)){ for (int i=1;i<=2*n;i++) if (vis[i]) printf("%d ",i); } else printf("NIE "); } return 0; }