hdu-1814(2-sat)
题意:给你n个组,m条规则,每组有俩个人,这两个人不能同时出现,然后m条规则代表着有两个人,这两个人也不能同时出现,问你是否存在每组都能出现一人的选择方案
解题思路:因为这个需要字典序输出,所以只能用暴力的方法解决,如果x,y在同一条规则里面,那么建立一条边由x指向和y同一组的另一个人,y也这样做,然后开始暴力dfs
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<queue> #include<vector> #define oth(x) (x%2==0?x-1:x+1) using namespace std; const int maxn=20050; int n,m,cnt; bool mark[maxn]; vector<int>e[maxn]; int ans[maxn]; bool dfs(int x) { if(mark[oth(x)]) return false; if(mark[x]) return true; mark[x]=true; ans[++cnt]=x; for(int i=0;i<e[x].size();i++) if(!dfs(e[x][i])) return false; return true; } bool twosat() { memset(mark,0,sizeof(mark)); for(int i=1;i<=n;i+=2) { if(!mark[i]&&!mark[oth(i)]) { cnt=0; if(!dfs(i)) { for(int j=1;j<=cnt;j++) mark[ans[j]]=mark[oth(ans[j])]=0; if(!dfs(oth(i))) return false; } } } return true; } int main() { int x,y; while(scanf("%d%d",&n,&m)!=EOF) { n=n*2; for(int i=0;i<=n;i++) e[i].clear(); for(int i=1;i<=m;i++) { cin>>x>>y; e[x].push_back(oth(y)); e[y].push_back(oth(x)); } if(twosat()) { for(int i=1;i<=n;i+=2) { if(mark[i]) printf("%d\n",i); else printf("%d\n",i+1); } } else printf("NIE\n"); } }