您的位置:首页 > 其它

UVAlive 6129 最小权匹配

2013-08-29 16:59 543 查看
题意:给你N个工人和N个工作,每个工作分为2个部分,必须先完成这个工作的第一部分,才能再做第二部分。每个工人分别完成一个工作的上下部分,不能完成两个工作的同一部分。

最后输出每个工人完成的工作的部分,和总时间。

最后输出一个等待的时间。

思路:

分两次进行匹配,先对每个工作的第一部分进行匹配,做一次最小权匹配,然后对于第二部分,我们进行建图的时候就要注意,当前工作的上部分是否已经完成,所以假设我们要做第二部分工作的时候,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

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: