UVAlive 6129 最小权匹配
2013-08-29 16:59
543 查看
题意:给你N个工人和N个工作,每个工作分为2个部分,必须先完成这个工作的第一部分,才能再做第二部分。每个工人分别完成一个工作的上下部分,不能完成两个工作的同一部分。
最后输出每个工人完成的工作的部分,和总时间。
最后输出一个等待的时间。
思路:
分两次进行匹配,先对每个工作的第一部分进行匹配,做一次最小权匹配,然后对于第二部分,我们进行建图的时候就要注意,当前工作的上部分是否已经完成,所以假设我们要做第二部分工作的时候,i -> j ,那么先求出i完成第一部分的时间,然后求出j工作在第一部分被完成的时间。然后两者取最大值,加上j工作在第二部分被i完成的时间,就是i ->j的第二部分的权值。
然后再做一遍匹配就可以了。
CODE:
最后输出每个工人完成的工作的部分,和总时间。
最后输出一个等待的时间。
思路:
分两次进行匹配,先对每个工作的第一部分进行匹配,做一次最小权匹配,然后对于第二部分,我们进行建图的时候就要注意,当前工作的上部分是否已经完成,所以假设我们要做第二部分工作的时候,i -> j ,那么先求出i完成第一部分的时间,然后求出j工作在第一部分被完成的时间。然后两者取最大值,加上j工作在第二部分被i完成的时间,就是i ->j的第二部分的权值。
然后再做一遍匹配就可以了。
CODE:
#include <set> #include <map> #include <stack> #include <cmath> #include <queue> #include <cstdio> #include <string> #include <vector> #include <iomanip> #include <cstring> #include <iostream> #include <algorithm> #define Max 2505 #define FI first #define SE second #define ll long long #define PI acos(-1.0) #define inf 0x3fffffff #define LL(x) ( x << 1 ) #define bug puts("here") #define PII pair<int,int> #define RR(x) ( x << 1 | 1 ) #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i ) using namespace std; inline void RD(int &ret) { char c; int flag = 1 ; do { c = getchar(); if(c == '-')flag = -1 ; } while(c < '0' || c > '9') ; ret = c - '0'; while((c=getchar()) >= '0' && c <= '9') ret = ret * 10 + ( c - '0' ); ret *= flag ; } inline void OT(int a) { if(a >= 10)OT(a / 10) ; putchar(a % 10 + '0') ; } inline void RD(double &ret) { char c ; int flag = 1 ; do { c = getchar() ; if(c == '-')flag = -1 ; } while(c < '0' || c > '9') ; ll n1 = c - '0' ; while((c = getchar()) >= '0' && c <= '9') { n1 = n1 * 10 + c - '0' ; } ll n2 = 1 ; while((c = getchar()) >= '0' && c <= '9') { n1 = n1 * 10 + c - '0' ; n2 *= 10 ; } ret = flag * (double)n1 / (double)(n2) ; } /*********************************************/ #define N 55 int a ; int b ; int n ; int Map ; int lx , ly , visx , visy , linky ,linkx ; int slx ,sly , slinky , slinkx ; int firstsolve ; int gap ; int find(int now){ visx[now] = 1 ; for (int i = 1 ; i <= n ; i ++ ){ if(!visy[i]){ int fk = Map[now][i] - lx[now] - ly[i] ; if(!fk){ visy[i] = 1 ; if(linky[i] == -1 || find(linky[i])){ linky[i] = now ; linkx[now] = i ; return 1 ; } } } } return 0 ; } int KM(){ mem(linky ,-1) ; mem(linkx, -1) ; mem(ly ,0) ; // bug ; for (int i = 1 ; i <= n ; i ++ ){ // bug ; while(1){ mem(visx, 0) ;mem(visy ,0) ; if(find(i))break ; // bug ; int d = inf ; for (int j = 1 ; j <= n ; j ++ ) if(visx[j]) for (int k = 1 ; k <= n ; k ++ ) if(!visy[k]) d = min(d , Map[j][k] - lx[j] - ly[k]) ; for (int j = 1 ; j <= n ; j ++ ){ if(visx[j])lx[j] += d ; if(visy[j])ly[j] -= d ; } } } int ans = 0 ; for (int i = 1 ; i <= n ; i ++ ){ if(linky[i] != -1)ans += Map[linky[i]][i] ; } return ans ; } int main() { int ca = 0 ; while(cin >> n , n){ for (int i = 1 ; i <= n ; i ++ ){ for (int j = 1 ; j <= n ; j ++ ){ cin >> a[i][j] ; } } for (int i = 1 ; i <= n ; i ++ ){ for (int j = 1 ; j <= n ; j ++ ){ cin >> b[i][j] ; } } for (int i = 1 ; i <= n ; i ++ ){ lx[i] = inf ; for (int j = 1 ; j <= n ; j ++ ){ Map[i][j] = a[i][j] ; lx[i] = min(lx[i] , a[i][j]) ; } } int ans1 = KM() ; // for (int i = 1 ; i <= n ; i ++ ){ // cout << i << " " << linkx[i] << " " << Map[i][linkx[i]] << endl; // } // cout << endl; for (int i = 1 ; i <= n ; i ++ ){ firstsolve[i] = lx[i] + ly[linkx[i]] ; } for (int i = 1 ; i <= n ; i ++ ){ slx[i] = lx[i] ; sly[i] = ly[i] ; slinky[i] = linky[i] ; slinkx[i] = linkx[i] ; // firs } mem(gap ,0) ; // cout << Map[1][2] << " hrer" << endl; // cout << slinky[2] << " hrere" << endl; for (int i = 1 ; i <= n ; i ++ ){ lx[i] = inf ; for (int j = 1 ; j <= n ; j ++ ){ int tx = slx[i] + sly[linkx[i]] ; int ty = a[slinky[j]][j] ; int tt = max(tx , ty) ;//求出两者的最大值。 if(ty > tx){ gap[i][j] = ty - tx ;//记录两点的差值,即工人等待的时间。 } Map[i][j] = tt + b[i][j] ; lx[i] = min(lx[i] , Map[i][j]) ; } } int ans2 = KM() ; int sum = 0 ; printf("Case %d:\n", ++ ca) ; for (int i = 1 ; i <= n ; i ++ ){ printf("Worker %d: ",i) ; cout << slinkx[i] << " " << linkx[i] << " " << Map[i][linkx[i]] << endl ; sum += gap[i][linkx[i]] ; } printf("Total idle time: %d\n",sum) ; } return 0 ; } /* 4 8 6 12 19 13 2 18 10 9 15 16 17 5 18 4 10 2 6 3 3 8 5 9 2 5 8 4 3 4 4 5 2 0 */
相关文章推荐
- UVALive 6198 A Terribly Grimm Problem 二分匹配 求字典序最小解
- Taxi Cab Scheme UVALive - 3126 最小路径覆盖解法(必须是DAG,有向无环图) = 结点数-最大匹配
- UVALIVE 4970 最小权匹配
- UVa live6492Welcome Party(二分最大匹配之最小点覆盖)
- UVALIVE 4970 最小权匹配
- Fixed Partition Memory Management UVALive - 2238 建图很巧妙 km算法左右顶点个数不等模板以及需要注意的问题 求最小权匹配
- uva 1411 Ants (权值和最小的完美匹配---KM算法)
- Similarity HDU 3718||UVALive - 5013 二分图最大权匹配
- UVALive 6322 最大匹配...
- Guardian of Decency UVALive - 3415 最大独立集=结点数-最大匹配数 老师带大学生旅游
- UVALive 5099 Nubulsa Expo 全局最小割问题
- 【UVALive】7502 Suffixes and Palindromes【根据sa数组以及回文半径数组构造字典序最小的串】
- UVALive - 4043 Ants (二分图最大权匹配)
- UVALive-5013 Similarity(二分图最大权匹配)
- UVALive 7264 Kejin Game(最小割)
- UVAlive 6571 最小路径覆盖变形(带权) 拆点+ISAP
- uva 11419(最大匹配,最小点覆盖)
- [二分图最大匹配=最小覆盖点]uva12549 Sentry Robots
- UVAlive 7368 Airports(建图+最小路径覆盖)
- UVALive 3662 Another Minimum Spanning Tree 曼哈顿最小生成树