hdu 2768 二分图匹配(难想到)

来源:互联网 发布:哪里能买到数据 编辑:程序博客网 时间:2024/05/29 02:32
题意:有v个观众,每个人投给自己喜欢的猫(或者狗)和讨厌的狗(或者猫),如果出现喜欢的和别人讨厌的相同,则其中一人会不满意。 
现要求得是最大满意的观众是多少。 

方法:根据出现矛盾的两个观众序号建边。现在选择最多的顶点,要求各个顶点之间没有线相连,即不出现矛盾。就是求最大独立集。

 最大匹配:二分图G中,找出边数最大的子图M,使得M中各条边均无公共顶点,则M为最大匹配。可用匈牙利算法求得。 
 最小顶点覆盖:二分图G中,找出顶点数最少的子图M,使得M中所有的点可以覆盖G中所有的边(一个顶点可以覆盖与它相连的边)。 
 最小顶点覆盖=最大匹配 

#include <bits/stdc++.h>  using namespace std;  vector<int> line[503];  bool used[503];  int girl[503];  int n,m,k;bool find(int x){      for (int j=0;j<line[x].size();j++){             int jj=line[x][j];          if (used[jj]==false){              used[jj]=1;              if (girl[jj]==-1 || find(girl[jj])) {                   girl[jj]=x;                  return true;}}}      return false;}  string a[503],b[503];int main(){    int t;    scanf("%d",&t);    while(t--){    cin>>k>>m>>n;        int all=0;          for(int i=0;i<n;++i)              line[i].clear();          memset(girl,-1,sizeof(girl));          for(int i=0;i<n;++i){            cin>>a[i]>>b[i];            for(int j=0;j<i;++j){                if(a[i]==b[j]||b[i]==a[j]){                    line[i].push_back(j);                    line[j].push_back(i);                }            }        }        for (int i=0;i<n;i++){              memset(used,0,sizeof(used));                 if (find(i))                     all+=1;          }          cout<<n-all/2<<endl;  //最小顶点覆盖,除2是因为两边有所重复     }    return 0;}
#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>using namespace std;struct node{    int cat,dog;}p1[505],p2[505];int c,d,v,num1,num2;int s[505][505],vis[505],match[505];int dfs(int x){    int i,j;    for(i=1;i<num2;i++){        if(!vis[i]&&s[x][i]){            vis[i]=1;            if(!match[i]||dfs(match[i])){                match[i]=x;                return 1;            }        }    }    return 0;}int hungarian(){    int i,sum;    sum=0;    for(i=1;i<num1;i++){        memset(vis,0,sizeof(vis));        if(dfs(i))        sum++;    }    return sum;}                                       //匈牙利算法模板int main(){                             //将喜欢猫的人放在左边的集合里喜欢狗的放在右面    int i,j,t,a,b;                      //将产生矛盾的连在一起再用v减掉,因此用到二分图    char ch;                            //匹配也就是匈牙利算法    scanf("%d",&t);    while(t--){        scanf("%d%d%d",&c,&d,&v);        num1=num2=1;        for(i=1;i<=v;i++){            scanf(" %c%d %c%d",&ch,&a,&ch,&b);            if(ch=='D'){                //喜欢猫的                p1[num1].cat=a;                p1[num1++].dog=b;            }            else{                       //喜欢狗的                p2[num2].cat=b;                p2[num2++].dog=a;            }        }        memset(s,0,sizeof(s));        memset(match,0,sizeof(match));        for(i=1;i<num1;i++)        for(j=1;j<num2;j++)        if(p1[i].cat==p2[j].cat||p1[i].dog==p2[j].dog)        s[i][j]=1;        printf("%d\n",v-hungarian());    }    return 0;}


0 0
原创粉丝点击