二分图匹配 --- 最大独立集

来源:互联网 发布:西南大学网络学费多少 编辑:程序博客网 时间:2024/05/29 17:23

结论 : 最大独立集 = 结点总数 - 最大匹配数(最小点覆盖数).
//解释: 最大独立集, 即选择尽量多的结点, 使得任意两个节点不相邻(即任意一条边的两个端点不会同时被选中), 最大独立集和最小点覆盖是互补的. 因此可以得出答案. 至于为什么是互补的, 就请好好想想. (白书P356)
//提示:
覆盖集 : 对于每条边, 至少有一个点要被选中.
独立集 : 对于每条边, 至少有一个点不被选中.

经典例题:
LA – 3415
//给出四个条件, 问你n个学生中最多可以挑多少个学生, 使得任意两个学生至少满足所给的四个条件中的一个.
//这样我们就可以根据最大独立集的概念知道这就是最大独立集的模型. 所以将每一个人作为一个结点, 如果两个四个条件都不满足, 那么他们就不能同时被选择, 连一条无向边. 因为每个人不是男生就是女生, 所以这个图是二分图. 求出最大独立集即可. (直接求当然很麻烦, 所以才用的结论啊!!!)

AC Code

/** @Cain*/const int maxn=500+5;bool g[maxn][maxn],vis[maxn];int link[maxn];int n;struct node{    int h;    char ginder[5],music[105],sport[105];}s[maxn];bool dfs(int x){    for(int i=1;i<=n;i++){        if(vis[i] || !g[x][i]) continue;        vis[i] = true;        if(link[i] == -1 || dfs(link[i])){            link[i] = x;            return true;        }    }    return false;}void solve(){    scanf("%d",&n);    Fill(g,false); Fill(link,-1); Fill(s,0);    for(int i=1;i<=n;i++){        scanf("%d%s%s%s",&s[i].h,s[i].ginder,s[i].music,s[i].sport);    }    for(int i=1;i<=n;i++){        for(int j=i+1;j<=n;j++){            if(abs(s[i].h-s[j].h)>40 || !strcmp(s[i].ginder,s[j].ginder))                continue;            if(strcmp(s[i].music,s[j].music)!=0 || !strcmp(s[i].sport,s[j].sport))                continue;            g[i][j] = g[j][i] =true;  //记住要连无向边!!!(否则为WA),最后的最大匹配数/2.因为连了两次.            //为什么要连无向边了,假如有4个学生,12,23,34不能在一起,如果是连单向边则答案是1,但实际上答案是2            //这个显而易见,所以要连无向边才能满足这个性质. 实际上从题意上看也可以知道不可能答案为1. xx.            //好好理解下.        }    }    int res = 0;    for(int i=1;i<=n;i++){        Fill(vis,false);        if(dfs(i)) res++;    }    printf("%d\n",n-res/2);}
原创粉丝点击