您的位置:首页 > 其它

2-sat(2011年成都现场赛)

2012-09-07 13:04 309 查看
/*
在2-sat中,i和j冲突,连两条有向边i-->j',j-->i'。
那么当i和j要求不同时,如果i和j相同,就表示i和j冲突,连两条有向边i-->j',j-->i'。
那么当i和j要求相同时,如果i和j不同,就表示i和j冲突,连两条有向边i-->j',j-->i'。
求强连通分量,如果i和i'在同一SCC中,则无解,输出no,否则输出yes。
*/
#include<cstdio>
#include<cstring>
#include<vector>
#define N 20005
using namespace std;

int n,m,t,tt,num,adj
;
int a[2]
,scc
,stk
,stk2
,dfn
;
struct edge
{
    int v,pre;
} e
;
void insert(int u,int v)
{
    e[num].v=v;
    e[num].pre=adj[u];
    adj[u]=num++;
}
void tarjan(int cur,int& sig,int& num)
{
    int i,v;
    dfn[cur]=++sig;
    stk[++stk[0]]=stk2[++stk2[0]]=cur;
    for(i=adj[cur]; ~i; i=e[i].pre)
        if(0==dfn[v=e[i].v])
            tarjan(v,sig,num);
        else if(0==scc[v])
            while(dfn[stk2[stk2[0]]]>dfn[v])
                stk2[0]--;
    if(stk2[stk2[0]]==cur)
    {
        stk2[0]--;
        num++;
        do
        {
            scc[stk[stk[0]]]=num;
        }
        while(stk[stk[0]--]!=cur);
    }
}
int Gabow()
{
    int i,sig,num;
    sig=num=stk[0]=stk2[0]=0;
    memset(scc,0,sizeof(scc));
    memset(dfn,0,sizeof(dfn));
    for(i=0; i<n*2; i++)
        if(0==dfn[i])
            tarjan(i,sig,num);
    return num;
}
bool check()
{
    for(int i=0; i<n*2; i+=2)
        if(scc[i]==scc[i+1])
            return 0;
    return 1;
}
int main()
{
    int i,j,u,v,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=0; i<n; i++)
        {
            scanf("%d",&a[0][i]);
            a[0][i]--;
            a[1][i]=(a[0][i]+2)%3;
        }
        num=0;
        memset(adj,-1,sizeof(adj));
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&k);
            u--;
            v--;
            for(i=0; i<2; i++)
                for(j=0; j<2; j++)
                    if(k&&a[i][u]==a[j][v]||!k&&a[i][u]!=a[j][v])
                    {
                        insert(2*u+i,2*v+j^1);
                        insert(2*v+j,2*u+i^1);
                    }
        }
        Gabow();
        printf("Case #%d: ",++tt);
        if(check())
            puts("yes");
        else
            puts("no");
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: