1047 - Best couple 好题~
Posted stupid_one
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1047 - Best couple 好题~相关的知识,希望对你有一定的参考价值。
http://www.ifrog.cc/acm/problem/1047
思路很简单,跑一发floyd,然后再用km。
但是问题来了,这个有可能n != m。那怎么办?
其实可以补上一些不存在的点。来使得n = m。他们的权值就设置为0就好了。意思就是这些人的搭配,是对答案没有贡献的。注意不能设置为-inf。因为补上的那些点也是必须要选人的,只不过他们选了人,相当于没选而已(权值不存在。)如果设置为-inf的那些,那么他们就会把答案改了。
还有一个小trick的就是,一开始,我是把本来地图上的-1的那些点,更改为inf的,inf表示不连通,那么直接floyd就可以了不用特判那么多。那么问题又来了。如果跑了floyd后,还是不连通,那怎么办?他们的权值可是inf啊。组成新图的时候,同时也是需要把他们的权值设置为0的,也就是相当于没选。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #define ios ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 1e2 + 20; int e[maxn][maxn]; int TE[2 * maxn][2 * maxn]; int match[maxn];//match[col] = row int vx[maxn],vy[maxn]; int fx[maxn],fy[maxn]; int n, m; int dfs (int u) { vx[u]=1; int i; for (i=1; i<=m; i++) { //筛选n个 导航员 col的值 if (vy[i]==0&&fx[u]+fy[i]==e[u][i]) { vy[i]=1; if (match[i]==0||dfs(match[i])) { match[i]=u;// match[col]=row; return 1;//搭配成功 } } } return 0;//我找不到啊,后面,就会执行km } void do_km() { // int i,j; int d=inf; for (i=1; i<=n; i++) { //遍历每一个驾驶员 row的值 if (vx[i]==1) { for (j=1; j<=m; j++) { //对他进行遍历导航员 col的值 if (!vy[j]) { if (d>(fx[i]+fy[j]-e[i][j])) { d=fx[i]+fy[j]-e[i][j]; } } } } } for (i=1; i<=n; i++) { if (vx[i]==1) { fx[i] -= d; vx[i]=0;//请0 } if (vy[i]==1) { // fy[i] += d; vy[i]=0;//情0 } } return ; } int anskm() { memset (vx,0,sizeof(vx)); memset (vy,0,sizeof(vy)); memset (fx,0,sizeof(fx)); memset (fy,0,sizeof(fy)); memset (match,0,sizeof(match)); //km算法的一部分,先初始化fx,fy for (int i=1; i<=n; i++) { //遍历每一个驾驶员 row的值 fy[i]=0; fx[i]= -inf;//无穷小 for (int j=1; j<=m; j++) { //遍历每一个导航员 col的值 if (fx[i]<e[i][j]) { //默契值 fx[i]=e[i][j]; } } } for (int i=1; i<=n; i++) { //遍历每一个驾驶员 row的值 memset (vx,0,sizeof(vx)); memset (vy,0,sizeof(vy)); while (!dfs(i)) {//如果他找不到搭配,就实现km算法 do_km();//km完后,还是会对这个想插入的节点进行dfs的,因为他还没搭配嘛 } // if (t == m) break; } int ans=0; for (int i=1; i<=m; i++) //遍历导航员,col的值 ans += e[match[i]][i];//输入的row是驾驶员,col是导航员 //match[i]:导航员i和驾驶员match[i]搭配了 match[col]=row; return ans; } void work() { memset(TE, 0, sizeof TE); memset(e, 0, sizeof e); cin >> n >> m; for (int i = 1; i <= n + m; ++i) { for (int j = 1; j <= n + m; ++j) { cin >> TE[i][j]; if (TE[i][j] == -1) TE[i][j] = inf; } } for (int k = 1; k <= n + m; ++k) { for (int i = 1; i <= n + m; ++i) { for (int j = 1; j <= n + m; ++j) { if (TE[i][j] > TE[i][k] + TE[k][j]) { TE[i][j] = TE[i][k] + TE[k][j]; } } } } // for (int i = 1; i <= n + m; ++i) { // for (int j = 1; j <= n + m; ++j) { // cout << TE[i][j] << " "; // } // cout << endl; // } // cout << endl; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { e[i][j] = TE[i][n + j]; if (e[i][j] == inf) { e[i][j] = 0; //不联通,要用0代替 } } } if (n > m) { for (int i = 1; i <= n; ++i) { for (int j = m + 1; j <= n; ++j) { e[i][j] = 0; } } m = n; } else if (n < m) { for (int i = n + 1; i <= m; ++i) { for (int j = 1; j <= m; ++j) { e[i][j] = 0; } } n = m; } cout << anskm() << endl; } int main() { #ifdef local freopen("data.txt","r",stdin); #endif IOS; int t; cin >> t; while (t--) work(); return 0; }
以上是关于1047 - Best couple 好题~的主要内容,如果未能解决你的问题,请参考以下文章
耦合 Coupling the object-oriented paradigm && data coupling
C 语言中 Mainframe TN3270(代码页 1047,1147,500,249)上的字符串/正则表达式字符 '[', ']', '', '' 替换为空格