题解:
2-sat
见图还是最难的。。。
每一对有奸情的都建对方连边
代码:
#include <cstdio> #include <queue> #include <cstring> #include <iostream> using namespace std; const int M=2005,N=3000010; int head[M],head1[M],edgeNum,edgeNum1,cnt,scnt,begin,n,m,low[M]; int dfn[M],stack[M],id[M],oppo[M],in[M],col[M],instack[M],ans[M]; struct edge{int v,next;}edge[N],edge1[N]; void add(int a,int b) { edge[edgeNum].v=b; edge[edgeNum].next=head[a]; head[a]=edgeNum++; } void add1(int a,int b) { edge1[edgeNum1].v=b; edge1[edgeNum1].next=head1[a]; head1[a]=edgeNum1++; } void dfs(int x) { low[x]=dfn[x]=++cnt; stack[++begin]=x; instack[x]=1; int v; for (int i=head[x];i!=-1;i=edge[i].next) { v=edge[i].v; if (!dfn[v]) { dfs(v); low[x]=low[v]<low[x]?low[v]:low[x]; } else if (instack[v]&&dfn[v]<low[x])low[x]=dfn[v]; } if (low[x]==dfn[x]) { scnt++; do { v=stack[begin--]; instack[v]=0; id[v]=scnt; }while(v!=x); } return ; } bool solve(int n) { cnt=scnt=begin=0; memset(dfn,0,sizeof(dfn)); memset(instack,0,sizeof(instack)); for (int i=0;i<2*n;i++) if (!dfn[i]) dfs(i); for (int i=0;i<n;i++) { if (id[i]==id[i+n]) return 0; oppo[id[i]]=id[i+n]; oppo[id[i+n]]=id[i]; } memset(in,0,sizeof(in)); memset(col,0,sizeof(col)); for (int i=0;i<2*n;i++) for (int j=head[i];j!=-1;j=edge[j].next) { int v=edge[j].v; if (id[i]!=id[v]) { in[id[i]]++; add1(id[v],id[i]); } } queue<int> que; for (int i=0;i<=scnt;i++) if (!in[i]) que.push(i); while(!que.empty()) { int now=que.front(); que.pop(); if (!col[now]) { col[now]=1; col[oppo[now]]=-1; } for (int i=head1[now];i!=-1;i=edge1[i].next) { int v=edge1[i].v; if (--in[v]==0) que.push(v); } } memset(ans,0,sizeof(ans)); for (int i=0;i<n;i++) if (col[id[i]]==1)ans[i]=1; return 1; } int main() { int a,b; char c,d; while (scanf("%d%d",&n,&m)!=EOF) { if (!n&&!m) break; edgeNum=edgeNum1=0; memset(in,0,sizeof(in)); memset(id,0,sizeof(id)); memset(head,-1,sizeof(head)); memset(head1,-1,sizeof(head1)); while (m--) { scanf("%d%c %d%c",&a,&c,&b,&d); if (c=='h'&&d=='h'){add(b+n,a);add(a+n,b);} if (c=='h'&&d=='w'){add(a+n,b+n);add(b,a);} if (c=='w'&&d=='h'){add(a,b);add(b+n,a+n);} if (c=='w'&&d=='w'){add(a,b+n);add(b,a+n);} } add(0,0+n); if (solve(n)) { for (int i=1;i<n;i++) { if (ans[i]) printf("%dh ",i); else printf("%dw ",i); } printf(" "); } else puts("bad luck"); } return 0; }