HDU - 3829 二分图的最大独立集

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3829
题目大意:
图片说明
图片说明
思路:如果A喜欢==B不喜欢||A不喜欢==B喜欢。那么A和B不能同时满足。连一条边。因为如果孩子的喜欢动物是猫,那么他/她的不喜欢动物一定是狗,反之亦然。那么可以证明一定一个二分图。就是求二分图的最大独立集。

#include  <map>
#include  <set>
#include  <cmath>
#include  <queue>
#include  <cstdio>
#include  <vector>
#include  <climits>
#include  <cstring>
#include  <cstdlib>
#include  <iostream>
#include  <algorithm>
#define LL long long
using namespace std;

const int INF=1e9;
const int maxn=505;// 最大点数
vector<int> G[maxn];
int Mx[maxn],My[maxn],Nx,Ny;//Mx[i]表示左集合i顶点所匹配的右集合的顶点序号
int dx[maxn],dy[maxn],dis;//My[i]表示右集合i顶点所匹配的左集合的顶点序号
bool vis[maxn];

 //寻找 增广路径集
bool searchP(){
    queue<int> q;
    dis=INF;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=1;i<=Nx;i++){
        if(Mx[i]==-1){
            q.push(i);dx[i]=0;
        }
    }
    while(!q.empty()){
        int u=q.front();q.pop();
        if(dx[u]>dis) break;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(dy[v]==-1){
                dy[v]=dx[u]+1;
                if(My[v]==-1) dis=dy[v];
                else{
                    dx[My[v]]=dy[v]+1;
                    q.push(My[v]);
                }
            }
        }
    }
    return dis!=INF;
}
//寻找路径 深度搜索
bool dfs(int u){
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(!vis[v]&&dy[v]==dx[u]+1){
            vis[v]=1;
            if(My[v]!=-1&&dy[v]==dis) continue;
            if(My[v]==-1||dfs(My[v])){
                My[v]=u;
                Mx[u]=v;
                return true;
            }
        }
    }
    return false;
}
//得到最大匹配的数目
int MaxMatch(){
    int res=0;
    memset(Mx,-1,sizeof(Mx));
    memset(My,-1,sizeof(My));
    while(searchP()){
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=Nx;i++){
            if(Mx[i]==-1&&dfs(i)) res++;
        }
    }
    return res;
}

string s1[505], s2[505];
int main(){
    int n1, n2, n3;
    string a, b;
    while(~scanf("%d%d%d", &n1, &n2, &n3)){
        for(int i=1; i<=n3; i++){
            cin>>a>>b;
            s1[i]=a;
            s2[i]=b;
        }
        for(int i=1; i<=n3; i++){
            for(int j=i+1; j<=n3; j++){
                if(s1[i]==s2[j]||s2[i]==s1[j]){
                    G[i].push_back(j);
                    G[j].push_back(i);
                }
            }
        }
        Nx=Ny=n3;
        printf("%d\n", n3-MaxMatch()/2);
        for(int i=1; i<=n3; i++) G[i].clear();
    }

    return 0;
}
全部评论

相关推荐

Noob1024:一笔传三代,人走笔还在
点赞 评论 收藏
分享
12-02 14:27
Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务