• Cat vs. Dog


    Cat vs. Dog

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 276 Accepted Submission(s): 106
     
    Problem Description
    The latest reality show has hit the TV: ``Cat vs. Dog''. In this show, a bunch of cats and dogs compete for the very prestigious Best Pet Ever title. In each episode, the cats and dogs get to show themselves off, after which the viewers vote on which pets should stay and which should be forced to leave the show.

    Each viewer gets to cast a vote on two things: one pet which should be kept on the show, and one pet which should be thrown out. Also, based on the universal fact that everyone is either a cat lover (i.e. a dog hater) or a dog lover (i.e. a cat hater), it has been decided that each vote must name exactly one cat and exactly one dog.

    Ingenious as they are, the producers have decided to use an advancement procedure which guarantees that as many viewers as possible will continue watching the show: the pets that get to stay will be chosen so as to maximize the number of viewers who get both their opinions satisfied. Write a program to calculate this maximum number of viewers.
     
    Input
    On the first line one positive number: the number of testcases, at most 100. After that per testcase:

    * One line with three integers c, d, v (1 ≤ c, d ≤ 100 and 0 ≤ v ≤ 500): the number of cats, dogs, and voters.
    * v lines with two pet identifiers each. The first is the pet that this voter wants to keep, the second is the pet that this voter wants to throw out. A pet identifier starts with one of the characters `C' or `D', indicating whether the pet is a cat or dog, respectively. The remaining part of the identifier is an integer giving the number of the pet (between 1 and c for cats, and between 1 and d for dogs). So for instance, ``D42'' indicates dog number 42.
     
    Output
    Per testcase:

    * One line with the maximum possible number of satisfied voters for the show.
     
    Sample Input
    2
    1 1 2
    C1 D1
    D1 C1
    1 2 4
    C1 D1
    C1 D1
    C1 D2
    D2 C1
     
    Sample Output
    1
    3
     
     
    Source
    NWERC 2008
     
    Recommend
    lcy
     
    /*
    题意:一集动画片是由c只猫,d只狗组成的,每一集都会有猫留下还是狗留下,有v个观众,给出每个观众喜欢的人和不喜欢的人,问怎么样安排动画片的
    结局才能使观众满意度最大,输出最大满意度的观众数量
    
    初步思路:将喜欢的动物和不喜欢的动物连边,然后找出最大匹配
    #错误:题意理解错了,要求的是最多留下的观众数量,而不是动物数量,这样比较每个观众如果两个观众,一个观众的喜欢的动物和另一个观众不喜欢的
    动物相同,那么这两个观众就是矛盾的就需要连边,将所有的边建完之后,然后考虑最大匹配问题
    
    #很奇怪加单向边就WA,加双向边就AC
    */
    #include<bits/stdc++.h>
    using namespace std;
    int c,d,m;
    int t;
    char op1[100],op2[100];
    struct node{
        string like,hate;
        node(){}
        node(string a,string b){
            like=a;
            hate=b;
        }
    };
    node fr[550];
    int fx,fy;
    /***********************二分匹配模板**************************/
    const int MAXN=550;
    int uN,vN;  //u,v数目
    int g[MAXN][MAXN];//编号是0~n-1的 
    int linker[MAXN];//记录匹配点i的匹配点是谁
    bool used[MAXN];
    bool dfs(int u)//回溯看能不能通过分手来进行匹配
    {
        int v;
        for(v=0;v<m;v++)
            if(g[u][v]&&!used[v])
            //如果有这条边,并且这条边没有用过
            {
                used[v]=true;
                if(linker[v]==-1||dfs(linker[v]))//如果这个点没有匹配过,并且能找到匹配点,那么就可以以这个边作为匹配点
                {
                    linker[v]=u;
                    return true;
                }    
            }  
        return false;  
    }    
    int hungary()//返回最大匹配数
    {
        int res=0;
        int u;
        memset(linker,-1,sizeof(linker));
        for(u=0;u<m;u++)
        {
            memset(used,0,sizeof(used));
            if(dfs(u))//如果这个点有匹配点 
                res++;
        } 
        return res;   
    }
    /***********************二分匹配模板**************************/
    int change(string s){
        int cur=0;
        for(int i=0;i<s.size();i++){
            cur=cur*10+s[i]-'0';
        }
        return cur;
    }
    void init(){
        memset(g,0,sizeof g);
    }
    int main(){
        //freopen("in.txt","r",stdin);
        scanf("%d",&t);
        while(t--){
            init();
            scanf("%d%d%d",&c,&d,&m);
            for(int i=0;i<m;i++){
                scanf("%s%s",op1,op2);
                fr[i]=node(op1,op2);
            }
            for(int i=0;i<m;i++){
                for(int j=i+1;j<m;j++){
                    if(fr[i].like==fr[j].hate||fr[i].hate==fr[j].like){
                        g[i][j]=1;
                        g[j][i]=1;
                    }    
                }
            }//建图
            // int cur=hungary();
            // cout<<cur<<endl;
            printf("%d
    ",m-hungary()/2);
        }
        return 0;
    }
  • 相关阅读:
    贪心[2019.5.25]
    顺序统计算法[2019.5.25]
    polya/burnside 学习
    虚拟机上装uoj
    一些常用的数据结构维护手法
    发一个数据生成器
    圆方树学习
    四校联考 推冰块
    Codeforces Training S03E01泛做
    HAOI2015 泛做
  • 原文地址:https://www.cnblogs.com/wuwangchuxin0924/p/6202991.html
Copyright © 2020-2023  润新知