F - True Liars - poj1417(背包+并查集)

时间:2023-03-08 19:23:39
题意:有这么一群人,一群好人,和一群坏人,好人永远会说实话,坏人永远说假话,现在给你一组对话和好人与坏人的数目P1, P2。
数据里面的no是A说B是坏人, yes代表A说B是好人,就是这样,问题能不能从这些话里面得出来唯一的解,就是可以确定谁是好人谁是坏人,如果不能输出no,如果可以输出所有的好人。
分析,可以把这些人依据他们中的关系分成几个小集合,集合里面保存两类人的数目,然后DP求出来好人或者坏人是不是唯一的即可,‘
注意并查集时候可以这么认为凡是yes都是同类,no都是异类
///////////////////////////////////////////////////////////////

#include<iostream>

#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<queue>
using namespace std; const int maxn = ; struct people
{
    int father, relation;
    int same, other;//同类数目,和异类数目
    int True;//是说谎者还是诚实者
}p[maxn]; int dp[maxn][maxn]; int Find(int x)
{
    int k = p[x].father;
    if( p[x].father != x )
    {
        p[x].father = Find(k);
        p[x].relation = (p[x].relation+p[k].relation)%;
    }     return p[x].father;
} int main()
{
    int M, T, L;     while(scanf("%d%d%d", &M, &T, &L), M+T+L)
    {
        int i, j, u, v, ru, rv, ok=, d, N=T+L, k=;
        char s[];int f[maxn];//f记录最后小集体的头结点         for(i=; i<=N; i++)
        {
            p[i].father = i;
            p[i].other = ;
            p[i].same = ;//自己和自己是同类,所以最少也有一个
            p[i].relation = ;
            p[i].True = ;
        }         while(M--)
        {
            scanf("%d%d%s", &u, &v, s);             if(ok)continue;
            ru = Find(u), rv = Find(v);             if(s[] == 'y')
                d = ;//0表示同类,1表示异类
            else d = ;             if(ru == rv && (p[v].relation+p[u].relation)% != d)
                ok = ;
            else if(ru != rv)
            {
                p[ru].father = rv;
                p[ru].relation = (p[u].relation+p[v].relation+d)%;
            }
        }         if(!ok)//有可能说的话有矛盾
        {
            for(i=; i<=N; i++)
            {
                u = Find(i);
                if(u == i)
                    f[k++] = i;
                else
                {
                    p[u].other += p[i].relation;
                    p[u].same += -p[i].relation;
                }
            }             memset(dp, , sizeof(dp));             dp[][ p[ f[] ].same ] += ;
            dp[][ p[ f[] ].other ] += ;             for(i=; i<k; i++)
            {
                u = f[i];
                for(j=; j<=N; j++)
                {
                    if(dp[i-][j])
                    {
                        dp[i][ p[u].same+j ] += dp[i-][j];
                        dp[i][ p[u].other+j ] += dp[i-][j];
                    }
                }
            }
        }         if(dp[k-][L] !=  || ok)
            printf("no\n");
        else
        {
            for(i=k-; i>; i--)
            {
                u = f[i];
                v = p[u].same;
                if( (i!= && dp[i-][T-v] != ) || (i== && T==v) )
                {
                    p[u].True = ;
                    T -= v;
                }
                else
                    T -= p[u].other;
            }             for(i=; i<=N; i++)
            {
                u = p[i].father;
                if(p[u].True && !p[i].relation || p[u].True== && p[i].relation)
                    printf("%d\n", i);
            }
            printf("end\n");
        }
    }     return ;
}
/*
1 1 1
1 2 yes

*/