uva12083(二分图最大独立集)
来源:互联网 发布:hp网络交换机 编辑:程序博客网 时间:2024/06/05 00:26
https://vjudge.net/problem/UVA-12083(uva12083 点击打开链接)
思路:二分图的最大独立集(二分图中任选两点之间,都不会有边相连)。
分析:首先,二分图肯定不能有边将同一侧的点相连。他们只要满足四个条件中的一个就不会产生爱意,相反,如果四个条件都不满足,就会产生爱意。每个人要么男,要么女,这样同侧就肯定不会有边相连,然后左右两边建边。如果其他三个条件都不满足,就建一条无向边。所以这个问题就变成了选择尽量多的点,满足任意一条边的两个点都不能同时被选到。这就是最大独立集。
那么怎么解这个最大独立集?其实它是和最小点覆盖互补的。互补就是指,数目是总点数减最小覆盖,解集只要把最小覆盖里的“已选点”和“未选点”互换即可。
为什么是互补?看两者的定义是什么。
(1)最小覆盖集:对于每条边,至少有一个点被选中。
(2)最大独立集:对于每条边,至少有一个点不被选中。
每个最小覆盖集都和一个唯一的最大独立集互补,每个最大独立集也都和一个唯一的最小覆盖集互补。
所以,综上:
最大独立集:选择尽量多的点,满足任意一条边的两个端点不被同时选中。
解集:与最小覆盖集互补。最大独立集点数 = 总点数 - 最小覆盖集点数 = 总点数 - 最大匹配数。
代码:
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <cstdlib>using namespace std;const int maxn = 500 + 10;struct node{ int height; char sex; string music; string sport;}person[maxn];int t;int line[maxn];bool used[maxn];bool judge(const node a,const node b){ if(abs(a.height - b.height) <= 40 && a.sex != b.sex && a.music == b.music && a.sport != b.sport) return true; return false;}//板子:bool dfs(int x){//右边的点 for(int i = 1;i <= t;i++) { if(i != x && used[i] == false) { if(judge(person[i],person[x])) { used[i] = 1; if(line[i] == 0 || dfs(line[i])) { line[i] = x; return true; } } } } return false;}int main(){ int T; scanf("%d",&T); while(T--) { scanf("%d",&t); for(int i = 1;i <= t;i++) { cin >> person[i].height >> person[i].sex; cin >> person[i].music >> person[i].sport; } memset(line,0,sizeof(line)); int ans = 0; for(int i = 1;i <= t;i++)//左边的点 { memset(used,0,sizeof(used)); if(dfs(i)) ans++; } printf("%d\n",t - ans/2); }}
模板:
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N=1001;int n1,n2,k;//n1,n2为二分图的顶点集,其中x∈n1,y∈n2int map[N][N],vis[N],link[N];//link记录n2中的点y在n1中所匹配的x点的编号int find(int x){ int i; for(i=1;i<=n2;i++) { if(map[x][i]&&!vis[i])//x->i有边,且节点i未被搜索 { vis[i]=1;//标记节点已被搜索 //如果i不属于前一个匹配M或被i匹配到的节点可以寻找到增广路 if(link[i]==0||find(link[i])) { link[i]=x;//更新 return 1;//匹配成功 } } } return 0;}int main(){ int i,x,y,s=0; scanf("%d%d%d",&n1,&n2,&k); for(i=0;i<k;i++) { scanf("%d%d",&x,&y); map[x][y]=1; } for(i=1;i<=n1;i++) { memset(vis,0,sizeof(vis)); if(find(i)) s++; } printf("%d\n",s); return 0;}
- 总算明白了点儿,明天再看看几者的关系吧,困了。。。
阅读全文
0 0
- uva12083(二分图最大独立集)
- poj 2771 uva12083 Guardian of Decency(二分图最大独立集)
- 二分图最大独立集
- 二分图最大独立集
- 二分图最大独立集
- 二分图最大匹配 & 最大独立集
- hdu 3829 二分图最大独立集
- poj 2771 二分图最大独立集
- HDU2768二分图求最大独立集
- poj3692 Kindergarten 二分图最大独立集
- hdu4160 Dolls (二分图最大独立集)
- poj 1466 二分图 最大独立集
- 二分图最大独立集--poj2771
- 二分图最大独立集-poj1466
- poj1466 二分图最大独立集
- HDU1054Strategic Game【二分图最大独立集】
- poj3020 二分图匹配 最大独立集
- 二分图(最大独立集)
- MySQL多实例介绍
- 【bzoj3343】教主的魔法
- 数据库缓存
- Android异步消息处理机制学习笔记
- 数据库SQL优化大总结之 百万级数据库优化方案
- uva12083(二分图最大独立集)
- 注册golang程序为windows服务
- Hibernate的增删查改
- css 盒子模型理解
- lua 计算n的阶乘
- vijos 1565 多边形
- 问题:The MySQL server is running with the --skip-grant-tables option
- effect java 学习摘要(9)
- 算法提高 ADV-13 最小乘积(提高型)