HDU1150 匈牙利算法(求二分图最大匹配)
2016-01-16 10:30
369 查看
HDU1150
题目大意;有两台机器A和B以及N个需要运行的任务。每台机器有M种不同的模式,而每个任务都恰好在一台机器上运行。如果它在机器A上运行,则机器A需要设置为模式ai,如果它在机器B上运行,则机器A需要设置为模式bi。每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。
谈匈牙利算法自然避不开Hall定理
Hall定理:对于二分图G,存在一个匹配M,使得X的所有顶点关于M饱和的充要条件是:对于X的任意一个子集A,和A邻接的点集为T(A),恒有: |T(A)| >= |A|
匈牙利算法是基于Hall定理中充分性证明的思想,其基本步骤为:
1.任给初始匹配M;
2.若X已饱和则结束,否则进行第3步;
3.在X中找到一个非饱和顶点x0,
作V1 ← {x0}, V2 ← Φ;
4.若T(V1) = V2则因为无法匹配而停止,否则任选一点y ∈T(V1)\V2;
5.若y已饱和则转6,否则做一条从x0 →y的可增广道路P,M←M⊕E(P),转2;
6.由于y已饱和,所以M中有一条边(y,z),作 V1 ← V1 ∪{z}, V2 ← V2 ∪ {y}, 转4;
二分图的最小顶点覆盖数=最大匹配数
本题就是求最小顶点覆盖数的。
每个任务建立一条边。
最小点覆盖就是求最少的点可以连接到所有的边。本题就是最小点覆盖=最大二分匹配数。
注意一点就是:题目说初始状态为0,所以如果一个任务有一点为0的边不要添加。因为不需要代价
AC代码:
题目大意;有两台机器A和B以及N个需要运行的任务。每台机器有M种不同的模式,而每个任务都恰好在一台机器上运行。如果它在机器A上运行,则机器A需要设置为模式ai,如果它在机器B上运行,则机器A需要设置为模式bi。每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。
谈匈牙利算法自然避不开Hall定理
Hall定理:对于二分图G,存在一个匹配M,使得X的所有顶点关于M饱和的充要条件是:对于X的任意一个子集A,和A邻接的点集为T(A),恒有: |T(A)| >= |A|
匈牙利算法是基于Hall定理中充分性证明的思想,其基本步骤为:
1.任给初始匹配M;
2.若X已饱和则结束,否则进行第3步;
3.在X中找到一个非饱和顶点x0,
作V1 ← {x0}, V2 ← Φ;
4.若T(V1) = V2则因为无法匹配而停止,否则任选一点y ∈T(V1)\V2;
5.若y已饱和则转6,否则做一条从x0 →y的可增广道路P,M←M⊕E(P),转2;
6.由于y已饱和,所以M中有一条边(y,z),作 V1 ← V1 ∪{z}, V2 ← V2 ∪ {y}, 转4;
二分图的最小顶点覆盖数=最大匹配数
本题就是求最小顶点覆盖数的。
每个任务建立一条边。
最小点覆盖就是求最少的点可以连接到所有的边。本题就是最小点覆盖=最大二分匹配数。
注意一点就是:题目说初始状态为0,所以如果一个任务有一点为0的边不要添加。因为不需要代价
AC代码:
#include<stdio.h> #include<vector> #include<iostream> #include<string.h> #include<algorithm> using namespace std; vector < vector <int > >v; bool used[101],used1[101]; int beg[101]; int n,m,k,a,e,r; bool bfs(int to) { int s=beg[to]; for(int i=0; i<v[s].size(); i++) { int point=v[s][i]; if(used1[point]) continue; used1[point]=true; if(beg[point]==-1||bfs(point)) { beg[point]=s; return true; } } return false; } int slove() { int num=0; bool foo=false; memset(used,false,sizeof(used)); memset(beg,-1,sizeof(beg)); for(int i=0; i<n; i++) { for(int j=0; j<v[i].size(); j++) { if(beg[v[i][j]]==-1) { beg[v[i][j]]=i; used[i]=true; num++; if(i==0) foo=true; break; } } } for(int i=0; i<n; i++) { if(!used[i]) { if(!v[i].empty()) { memset(used1,false,sizeof(used1)); for(int j=0; j<v[i].size(); j++) { int point=v[i][j]; if(used1[point]) continue; used1[point]=true; if(beg[point]==-1||bfs(point)) { beg[point]=i; num++; break; } } } used[i]=true; } } if(beg[0]!=-1) num--; if(foo) return num-1; else return num; } int main() { while(scanf("%d",&n)&&n) { v.clear(); v.resize(n); scanf("%d%d",&m,&k); for(int i=0; i<k; i++) { scanf("%d%d%d",&a,&e,&r); v[e].push_back(r); } printf("%d\n",slove()); } }
相关文章推荐
- Tomcat中server.xml参数说明
- 完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三2-转
- asp.net站点500.12错误解决办法
- 【iCore3 双核心板】例程三十三:SD_IAP_ARM实验——更新升级STM32
- mapreduce yarn 的job提交流程
- HBase Memstore
- JAVA解决乱码之道
- 完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三 1-转
- Go学习笔记(1)Go语言介绍
- python paramiko模块
- 手把手教你玩转网络编程模型之完成例程(Completion Routine)篇(下)-转
- 手把手教你玩转网络编程模型之完成例程(Completion Routine)篇(上)-转
- 权限管理部分的一些设计与想法
- java(13)--配置https加密连接器并生成数字证书
- 【Java】上传文件进度条的实现方法(附demo源码下载)
- 人际关系处理技巧
- 【iCore3 双核心板】例程三十二:UART_IAP_ARM实验——更新升级STM32
- Android屏幕概念
- select模型使用例子
- Linux每日学习(八)