hdu2853 Assignment
来源:互联网 发布:前端ajax获取json数据 编辑:程序博客网 时间:2024/06/06 01:04
思路来自:http://www.cnblogs.com/kane0526/p/3263248.html
题意:有n个公司,m个任务,每个公司做每个任务都有一个效率值,最开始每个公司都指派了一个任务,现在要你重新给每个公司分配一个任务(一个任务只能分配给一家公司),使得所有公司任务的效率值最大,并且改变的原始任务最少。
思路:把每条边的权值扩大k倍(k>n),然后属于原始任务的边权值+1,权值加1是为了当两条边权值相同时,更优先选择属于原始任务的边,扩大k倍的巧妙之处不仅在于KM匹配时优先选择原始边所得答案除k得到原始答案,而且结果对k求余就是保留的就是原始任务的数量。
这题将权值扩大的思想和之前最小割求割边数的那个有点像,但是自己没想到,看了才想起来
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <vector>#include <map>#include <utility>#include <queue>#include <stack>using namespace std;const int INF=1e9;const double eps=1e-6;const int N = 550;int nx,ny;int g[N][N];int linker[N],lx[N],ly[N];int slack[N];int visx[N],visy[N];int n,m;bool DFS(int x){ visx[x]=true; for(int y=0;y<ny;y++) { if(visy[y]) continue; int tmp = lx[x]+ly[y]-g[x][y]; if(tmp==0) { visy[y]=true; if(linker[y]==-1||DFS(linker[y])) { linker[y]=x; return true; } } else if(slack[y]>tmp) slack[y]=tmp; } return false;}int KM(){ memset(linker,-1,sizeof(linker)); memset(ly,0,sizeof(ly)); for(int i=0;i<nx;i++) { lx[i]=-INF; for(int j=0;j<ny;j++) if(g[i][j]>lx[i]) lx[i]=g[i][j]; } for(int x=0;x<nx;x++) { for(int i=0;i<ny;i++) slack[i]=INF; while(true) { memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); if(DFS(x)) break; int d = INF; for(int i=0;i<ny;i++) if(!visy[i] && d>slack[i]) d=slack[i]; for(int i=0;i<nx;i++) if(visx[i]) lx[i]-=d; for(int i=0;i<ny;i++) { if(visy[i]) ly[i]+=d; else slack[i]-=d; } } } int res = 0, cnt = 0; for(int i=0;i<ny;i++) { if(linker[i]==-1) continue; res += g[linker[i]][i]; cnt++; } if(cnt!=nx) return -1; return res;}int main(){int i,j;while(scanf("%d%d",&nx,&ny)!=EOF){for(i=0;i<nx;i++){for(j=0;j<ny;j++){g[i][j]=-INF;}}for(i=0;i<nx;i++){for(j=0;j<ny;j++){int x;scanf("%d",&x);g[i][j]=max(x*100,g[i][j]);}}int sum=0; for(i=0;i<nx;i++){int x;scanf("%d",&x);x--;sum+=g[i][x]/100;g[i][x]++;//使得权相等的时候,优先选取已经存在的,那么ans%100就是匹配中,保留的边数 }int ans=KM();printf("%d %d\n",nx-ans%100,ans/100-sum);}return 0;}
阅读全文
0 0
- hdu2853 Assignment
- HDU2853 Assignment KM算法 巧妙变化
- hdu2853 Assignment (KM最少改动边)
- HDU2853-Assignment KM 限制边的交换
- hdu2853 Assignment(KM+双元限制)
- [HDU2853]Assignment(KM双元限制)
- KM匹配 hdu2853(模版
- Assignment
- Assignment 1
- Assignment 2
- Assignment 3
- Assignment 4
- Assignment 5
- Assignment 6
- Assignment 7
- Assignment 8
- Assignment 9
- Assignment 10
- 【牛客网】直通bat-面试算法精品课_第2章 排序 2.5 归并排序练习题(JAVA版)
- hdu-1258-Sum It Up(DFS)
- 区别#define、enum和const
- A Dangerous Maze LightOJ
- Polycarp and Letters
- hdu2853 Assignment
- poj 3984 bfs+路径还原
- 安卓 手写消息机制
- GET和POST有什么区别?
- 十字链表和邻接多重表
- 二分求根
- 软件工程 习题三 课后作业
- windows7下搭建robot framework环境指导
- Python 模块安装详细