• POJ1417 True Liars 题解


    通过读题,容易发现,当回答为yes(x,y) 必属于同类,当回答为no时二者必为异类(并且当 (x=y) 时,回答必为yes,不过这题不用这个性质)。
    于是先按关系维护连通块,然后求出每个连通块的人数,用背包看是否能够凑出。可以把一个连通块的看作一个物品,总共的天神数就是背包的容量。
    还用了set辅助维护每个连通块里具体是哪些人。
    这道题刚开始一直卡着,结果照着样例手玩一遍就全懂了,所以光空想还是不行的。
    具体看丑陋的代码吧……

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=1005,M=605;
    struct path{int r1,r2,rd1,rd2;}p[M];
    set<int> s[M<<1];
    int fa[M<<1],n,m,p1,p2,d[M<<1],f[M][M];
    
    int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    void merge(int x,int y) {fa[find(x)]=find(y);}
    
    int main()
    {
        while(~scanf("%d%d%d",&n,&p1,&p2)&&(n||p1||p2))
        {
            m=p1+p2;
            for(int i=1;i<=m+m;++i) fa[i]=i,s[i].clear();
            for(int i=1,x,y;i<=n;++i)
            {
                char s[5];
                scanf("%d %d %s",&x,&y,s);
                if(s[0]=='y') merge(x,y),merge(x+m,y+m);
                else merge(x,y+m),merge(x+m,y);
            }
            memset(d,0,sizeof(d));
            for(int i=1;i<=m;++i)
            {
                int x=find(i);
                d[x]++; s[x].insert(i);
            }
            int cnt=0;
            for(int i=1;i<=m+m;++i)
            {
                if(!d[i]) continue;
                int x=i<=m?i:i-m;int y=x+m;
                x=find(x),y=find(y);
                p[++cnt].r1=d[x];
                p[cnt].r2=d[y];
                p[cnt].rd1=x,p[cnt].rd2=y;
                d[x]=d[y]=0;
            }
            memset(f,0,sizeof(f));
            f[0][0]=1;
            for(int i=1;i<=cnt;++i)
                for(int j=p1;~j;--j)
                {
                    if(j>=p[i].r1) f[i][j]+=f[i-1][j-p[i].r1];
                    if(j>=p[i].r2) f[i][j]+=f[i-1][j-p[i].r2];
                }
            if(f[cnt][p1]!=1) puts("no");
            else
            {
                set<int> ans; int sum=p1;
                for(int i=cnt;i;--i)
                    if(f[i-1][sum-p[i].r1])
                        ans.insert(s[p[i].rd1].begin(),s[p[i].rd1].end()),sum-=p[i].r1;
                    else ans.insert(s[p[i].rd2].begin(),s[p[i].rd2].end()),sum-=p[i].r2;
                for(int i : ans) printf("%d
    ",i);
                puts("end");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    pandas,对dataFrame中某一个列的数据进行处理
    pandas的简单使用
    pandas,读取或存储DataFrames的数据到mysql中
    pandas,pd.ExcelWriter保存结果到已存在的excel文件中
    用命令让vbox的虚拟硬盘文件转换成vmware的vmdk
    vbox磁盘空间如何扩容
    Linux ext3/ext4数据恢复
    VirtualBox安装64位系统
    ubuntu 12.04启用休眠
    美化你的GRUB,全面支持中文(菜单、提示、帮助)适用7.04-9.04
  • 原文地址:https://www.cnblogs.com/wzzyr24/p/12268041.html
Copyright © 2020-2023  润新知