题意: 有n个组织,每个组织有两个人,第i组的两个人分别是2*i-1,2*i,其中有m对人相互讨厌,要在n个组织中各选一个人,使得没有任何两个人相互讨厌,如果存在答案,输出字典序最小的,如果无解,输出NIE
分析:如果i和j相互讨厌,那么那么如果选i,那么必定选j^1,选i^1必定选j,加入这两条边,跑2sat,字典序,用从小到大枚举来保证,如果找到一个解,立刻退出
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; struct sat{ int n; vector<int>G[maxn*2]; bool mark[maxn*2]; int S[maxn*2],c; bool dfs(int x){ if (mark[x^1]) return false; if (mark[x]) return true; mark[x]=true; S[c++]=x; for (int i=0;i<G[x].size();i++) if (!dfs(G[x][i])) return false; return true; } void init(int n){ this->n=n; for (int i=0;i<n*2;i++) G[i].clear(); memset(mark,0,sizeof(mark)); } void add_clause(int x,int xval,int y,int yval){ x=x*2+xval; y=y*2+yval; G[x^1].push_back(y); G[y^1].push_back(x); } void add(int x,int y){ G[x].push_back(y^1); G[y].push_back(x^1); } bool solve(){ for (int i=0;i<n*2;i+=2) if (!mark[i]&&!mark[i+1]){ c=0; if (!dfs(i)){ while (c>0) mark[S[--c]]=false; if (!dfs(i+1)) return false; } } return true; } }Sat; int main(){ int n,m; while(cin>>n>>m){ Sat.init(n); for(int i=0;i<m;i++){ int a,b; cin>>a>>b; a--;b--; //a=a>>1;b=b>>1; //Sat.add_clause(a,(a&1),b,(b&1)); Sat.add(a,b); } if(Sat.solve()){ for(int i=0;i<2*n;i+=2) if(Sat.mark[i]) cout<<i+1<<endl; else cout<<i+2<<endl; } else puts("NIE"); } return 0; }