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 的表示可选的 */
}
}