zoukankan      html  css  js  c++  java
  • [题解] uva 11383 Golden Tiger Claw (二分图最佳完美匹配)

    - 传送门 -

     https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2378

    # 11383 - Golden Tiger Claw Time limit: 8.000 seconds

    | Root | Submit Problem Stats
    uDebug Download as PDF |

    (题面见pdf)

     

    - 题意 -

     对于一个 N*N 矩阵, 每个格子有一个整数w(i,j), 对每行确定一个数row(i), 每一列确定一个数col(i), 使对于任意格子(i,j), w(i,j)<=row(i)+col(i), 所有的 row 和 col 的和要最小.
     

    - 思路 -

     发现(通过题解得知)这个 col 和 row 很像最佳匹配中的两个标杆...
     我们把列数和行数视为两个集合中的点, 边权就是格点上的数.
     对于任意一个点, 它和对面集合中的点连边的边权都小于两边标杆之和, 满足题意...
     km算法之后所有顶标之和是最小的(大概...是因为...就是...那个...记住就行...), 据此得出答案.
     反正就是个脑洞题呗...

     细节见代码.
     

    - 代码 -

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int inf = 0x7f7f7f7f;
    const int N = 500 + 5;
    
    int W[N][N], LX[N], LY[N];
    int SLACK[N], S[N], T[N], ANS[N];
    int n;
    
    bool find(int x) {
    	S[x] = true;
    	
    	for (int i = 1; i <= n; ++i) {
    		if (T[i]) continue;
    		
    		int tmp = LX[x] + LY[i] - W[x][i];
    		if (tmp == 0) {
    			T[i] = true;
    			if (ANS[i] == 0 || find(ANS[i])) {
    				ANS[i] = x;
    				return true;
    			}
    		}
    		else if (tmp < SLACK[i])
    			SLACK[i] = tmp;
    	}
    	
    	return false;
    }
    
    int km() {
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= n; ++j)
    			SLACK[j] = inf;
    		while (true) {
    			memset(S, 0, sizeof (S));
    			memset(T, 0, sizeof (T));
    			
    			if (find(i)) break;
    			
    			int d = inf;
    			for (int j = 1; j <= n; ++j) {
    				if (!T[j] && d > SLACK[j])
    					d = SLACK[j];
    			}
    			
    			for (int j = 1; j <= n; ++j) {
    				if (S[j]) LX[j] -= d;
    			}
    			
    			for (int j = 1; j <= n; ++j) {
    				if (T[j]) LY[j] += d;
    				else SLACK[j] -= d;
    			}
    			
    		}
    	}
    	int sum = 0;
    	for (int i = 1; i <= n; ++i)	
    		sum += LX[i] + LY[i];
    	return sum;
    }
    
    int main() {
    	
    	while(~scanf("%d", &n)) {
    		memset(LX, 0, sizeof (LX));
    		memset(LY, 0, sizeof (LY));
    		memset(ANS, 0, sizeof (ANS));
    		for (int i = 1; i <= n; ++i) {
    			for (int j = 1; j <= n; ++j) {
    				scanf("%d", &W[i][j]);
    				LX[i] = max(LX[i], W[i][j]);
    			}
    		}
    
    		int ans = km();
    
    		printf("%d", LX[1]);
    		for (int i = 2; i <= n; ++i)
    			printf(" %d", LX[i]);
    		printf("
    ");
    		printf("%d", LY[1]);
    		for (int i = 2; i <= n; ++i)
    			printf(" %d", LY[i]);
    		printf("
    ");
    		printf("%d
    ", ans);
    	}
    	return 0;
    	
    }
    
  • 相关阅读:
    MYSQL router 自动均衡负载
    mysql router 自动failover测试
    Oracle数据库安装时 environment variable path 大于 1023
    windows删除多余启动引导项
    开机显示 invalid partition table
    有关软件的商业模式与软件代码的加密
    .Net 开源控件 NPlot使用小结
    41.关于Intellij IDEA菜单项中Compile、Make和Build的区别
    Maven:mirror和repository 区别
    28. Spring Boot配置方式
  • 原文地址:https://www.cnblogs.com/Anding-16/p/7470084.html
Copyright © 2011-2022 走看看