给定一个N*N矩阵T,要求出两组值a[1..N],b[1..N],使得T[i,j]<=a[i]+b[j]。 这道题考察了KM算法的知识,把矩阵的元素值看作二分图的边权值,我们要求的实际上就是KM算法中用到的顶标! #include <cstdio> #include <cstring> #define MAX 103 using namespace std; int n; // X 的大小 int weight [MAX] [MAX]; // X 到 Y 的映射(权重) int lx [MAX], ly [MAX]; // 标号 bool sx [MAX], sy [MAX]; // 是否被搜索过 int match [MAX]; // Y(i) 与 X(match [i]) 匹配 void init () { for (int i = 0; i < n; i ++) for (int j = 0; j < n; j ++) weight[i][j]=0; } bool path (int u) { sx [u] = true; for (int v = 0; v < n; v ++) if (!sy [v] && lx[u] + ly [v] == weight [u] [v]) { sy [v] = true; if (match [v] == -1 || path (match [v])) { match [v] = u; return true; } } return false; } void bestmatch () { int i,j,temp; // 初始化标号 for (i = 0; i < n; i ++) { lx [i] = -0x1FFFFFFF; ly [i] = 0; for (j = 0; j < n; j ++) if (lx [i] < weight [i] [j]) lx [i] = weight [i] [j]; } memset (match, -1, sizeof (match)); for (int u = 0; u < n; u ++) while (1) { memset (sx, 0, sizeof (sx)); memset (sy, 0, sizeof (sy)); if (path (u)) break; // 修改标号 int dx = 0x7FFFFFFF; for (i = 0; i < n; i ++) if (sx [i]) for (j = 0; j < n; j ++) if(!sy [j]) { temp = lx[i] + ly [j] - weight [i] [j]; if(temp<dx) dx=temp; } for (i = 0; i < n; i ++) { if (sx [i]) lx [i] -= dx; if (sy [i]) ly [i] += dx; } } } int main() { while(scanf("%d",&n)!=EOF) { init(); for(int i=0;i<n;++i) for(int j=0;j<n;++j) scanf("%d",&weight[i][j]); bestmatch(); for(int i=0;i<n;++i) { if(i) printf(" "); printf("%d",lx[i]); } printf("/n"); for(int i=0;i<n;++i) { if(i) printf(" "); printf("%d",ly[i]); } printf("/n"); } return 0; }