URAL 1382 Game with Cards 解题报告

来源:互联网 发布:仿美团外卖小程序源码 编辑:程序博客网 时间:2024/04/25 12:30

题目

比赛

题意:

有N张牌,N个人,每个人会说两句话,"我拿着牌a"和"b拿着牌c",这两句话中有且只有一句话是对的。

求每个人说的话中哪一句话是对的,题目保证一定有解

思路:

2-sat,对于第i个人,有第一句是对的I1,第二句话是对的I2两种互斥的状态,可以把I1看成"i拿着牌a",则当两句话中人相同牌不同时,或者人不同牌相同时,这两句话产生冲突,然后就套用2-sat输出解的模板。

代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>using namespace std;#define maxN 1005#define maxn 2005#define maxm 5000005int n;struct node{    int s,t;    int next;}e[maxm],e2[maxm];int ecnt,ecnt2,pre[maxn],pre2[maxn];int a[maxn],b[maxn];void addEdge(int u,int v){    e[ecnt].s=u;    e[ecnt].t=v;    e[ecnt].next=pre[u];    pre[u]=ecnt++;}void addE(int u,int v){    e2[ecnt2].s=u;    e2[ecnt2].t=v;    e2[ecnt2].next=pre2[u];    pre2[u]=ecnt2++;}int Dindex,top,cnt;int dfn[maxn],low[maxn],bel[maxn];int stack[maxn];bool instack[maxn];void tarjan(int u){    int v;    dfn[u]=low[u]=++Dindex;    stack[++top]=u;    instack[u]=true;    for (int i=pre[u];i!=-1;i=e[i].next)    {        v=e[i].t;        if (!dfn[v])        {            tarjan(v);            if (low[v]<low[u]) low[u]=low[v];        }        else if (instack[v]&&dfn[v]<low[u])            low[u]=dfn[v];    }    if (dfn[u]==low[u])    {        cnt++;        do        {            v=stack[top--];            instack[v]=false;            bel[v]=cnt;        }while (u!=v);    }}void solve(){    Dindex=top=cnt=0;    for (int i=1;i<=2*n;i++)        if (!dfn[i]) tarjan(i);}int cf[maxn],in[maxn],col[maxn];bool ans[maxn];void re_build(){    ecnt2=0;    memset(pre2,-1,sizeof(pre2));    for (int i=0;i<ecnt;i++)    {        if (bel[e[i].s]!=bel[e[i].t])        {            addE(bel[e[i].t],bel[e[i].s]);            in[bel[e[i].s]]++;        }    }}void topsort(){    queue<int> q;    for (int i=1;i<=cnt;i++)        if (in[i]==0) q.push(i);    while (!q.empty())    {        int u=q.front();        q.pop();        if (col[u]==0)        {            col[u]=1;            col[cf[u]]=-1;        }        for (int i=pre2[u];i!=-1;i=e2[i].next)        {            int v=e2[i].t;            in[v]--;            if (in[v]==0)   q.push(v);        }    }}void make(){    solve();    for (int i=1;i<=n;i++)    {        cf[bel[i]]=bel[i+n];        cf[bel[i+n]]=bel[i];    }    re_build();    topsort();    for (int i=1;i<n;i++)        if (col[bel[i]]==1) printf("1 ");        else printf("2 ");    if (col[bel[n]]==1) printf("1\n");    else printf("2\n");}int main(){    //freopen("/home/moor/Code/input.txt","r",stdin);    scanf("%d",&n);    int x,y,z;    for (int i=1;i<=n;i++)    {        scanf("%d%d%d",&x,&y,&z);        a[i]=i; b[i]=x;        a[i+n]=y; b[i+n]=z;    }    ecnt=0;    memset(pre,-1,sizeof(pre));    for (int i=1;i<=2*n;i++)        for (int j=i+1;j<=2*n;j++)        {            if ((a[i]==a[j]&&b[i]!=b[j])||(a[i]!=a[j]&&b[i]==b[j]))            {                if (j<=n) addEdge(i,j+n);                else addEdge(i,j-n);                if (i<=n) addEdge(j,i+n);                else addEdge(j,i-n);            }        }    make();    return 0;}