2-sat方法传送
当初网络赛的时候只想到了2-sat方法,后来想想,哪要这么麻烦啊,随便染个色,证明一下是二分图不就完了么。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int n,a; int fst[105],next[20005],node[20005],en; bool vis[105]; int c[105],ans; bool p[105][105]; void init() { en=0; ans=0; memset(fst,-1,sizeof(fst)); memset(vis,0,sizeof(vis)); memset(p,0,sizeof(p)); } void add(int u,int v) { next[en]=fst[u]; fst[u]=en; node[en]=v; en++; next[en]=fst[v]; fst[v]=en; node[en]=u; en++; } void bfs(int s) { queue<int>q; q.push(s); vis[s]=1; c[s]=0; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=fst[u];i!=-1;i=next[i]) { int v=node[i]; if(!vis[v]) { vis[v]=1; c[v]=!c[u]; q.push(v); } else if(c[u]==c[v])ans=1; } } } int main() { while(scanf("%d",&n)!=EOF) { init(); for(int i=1;i<=n;i++) { while(scanf("%d",&a)) { if(a==0)break; p[i][a]=1; } } for(int i=1;i<n;i++) { for(int j=i+1;j<=n;j++) { if(p[i][j]&&p[j][i])continue; add(i,j); add(j,i); } } for(int i=1;i<=n;i++) { if(!vis[i])bfs(i); } if(ans==1)cout<<"NO"<<endl; else cout<<"YES"<<endl; } }