zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解
    一个自动安装LNMP的简洁Shell脚本
    (总结)Nginx配置文件nginx.conf中文详解
    Linux 的启动流程
    Linux运维文档之nginx
    nginx索引目录配置
    nginx实现图片防盗链(referer指令)
    nginx记录分析网站响应慢的请求(ngx_http_log_request_speed)
    C# 使用WinRar命令压缩和解压缩
    localStorage存值取值以及存取JSON,以及基于html5 localStorage的购物车
  • 原文地址:https://www.cnblogs.com/wzzyr24/p/12268041.html
Copyright © 2011-2022 走看看