int stk[N],vis[N],low[N],link[N],mark[N]; int top,index,id,du[N];//记录入度数 int pre[N],cnt,g[N];// g 用来记录topsort后的结果 int g1[N]; //用来记录缩点后的每一个点所含的点 void dfs(int s) { mark[s]=1; vis[s]=index++; low[s]=vis[s]; stk[top++]=s; for(int p=pre[s];p!=-1;p=edge[p].next) { int v=edge[p].to; if(mark[v]==0) dfs(v); if(mark[v]==1) low[s]=min(low[s],low[v]); } if(low[s]==vis[s]) { int tmp; id++; do { tmp=stk[top-1]; link[tmp]=id; mark[tmp]=-1; }while(stk[--top]!=s); } } void add_edge(int u,int v) { edge[cnt].from=u; edge[cnt].to=v; edge[cnt].next=pre[u]; pre[u]=cnt++; } void topsort() { memset(mark,0,sizeof(mark)); top=0; int tcnt=0; for(int i=1;i<=id;i++) if(du[i]==0) { mark[i]=1; stk[top++]=i;//把这个节点入栈 g[tcnt++]=i; } while(top!=0) { int cur=stk[--top]; for(int p=pre[cur];p!=-1;p=edge[p].next) { int v=edge[p].to; if(mark[v]==1) continue; du[v]--; if(du[v]==0) { mark[v]=1; stk[top++]=v; g[tcnt++]=v; } } } } void dfs1(int s) //将所有不可能的情况标记 { mark[s]=-1; for(int p=pre[s];p!=-1;p=edge[p].next) { int v=edge[p].to; dfs1(v); } } void sat2(int sn) //top 表示传入的点数。 其中要保证标号从0开始而且0和1是一组 { top=index=id=0; memset(mark,0,sizeof(mark)); for(int i=0;i<sn;i++) if(mark[i]==0) dfs(i); int flag=0; for(int i=0;i<sn;i+=2) { if(link[i]==link[i+1]) { flag=1; break; } } if(flag) { /* 当不可行的时候输出 */ printf("bad luck\n"); } else { /* 可行的时候输出 */ printf("YES\n"); int tcnt=cnt; memset(g1,0,sizeof(g1)); cnt=0; memset(pre,-1,sizeof(pre)); for(int i=0;i<sn;i++) { g1[ link[i] ]=i; } memset(du,0,sizeof(du)); for(int i=0;i<tcnt;i++) { int x=edge[i].from; int y=edge[i].to; if(link[x] != link[y]) { add_edge(link[y],link[x]);//建逆图 du[ link[x] ]++; } } topsort(); memset(mark,0,sizeof(mark)); for(int i=0;i<id;i++) { if(mark[ g[i] ]!=-1)//表示这个点可以选 { mark[ g[i] ]=1; int key=g1[ g[i] ]; key=key^1; key=link[key]; dfs1(key); } } /* print mark[ link[i] ]==1 的表示可选的 */ } }