原题 磨了三天,终于AC了,开始时照着书上写,心里很没底,发现如果有错,很难改,后来又到网上找代码,又看不懂。 最后下定决心自己写。思路参照2005年国家集训队王俊的论文。 #include <iostream> #include <algorithm> #define MAXN 70//数组开小了还WA了一次 #define MAXE 420 #define INF (1 << 28) using namespace std ; int num[MAXN][MAXN] , gg[MAXN][MAXN] , pre[MAXN] , n , m , depth[MAXN] , size , lx[MAXE] , ly[MAXE] , x[MAXE] , y[MAXE] , g[MAXE][MAXE] , link[MAXE] ; bool l[MAXE] , r[MAXE] ; void DFS (int i , int d) { for (int j = 1 ; j <= n ; j ++) if (num[i][j] && !pre[j]) { pre[j] = i ; depth[j] = d ; DFS (j , d + 1) ; } } int LCA (int a , int b) { int h1 , h2 ; h1 = depth[a] , h2 = depth[b] ; while (h1 > h2) h1 -- , a = pre[a] ; while (h2 > h1) h2 -- , b = pre[b] ; while (a != b) a = pre[a] , b = pre[b] ; return a ; } void BuildGraph (int k , int u , int v , int w) { int i , par ; par = LCA (u , v) ; for (i = u ; i != par ; i = pre[i]) if (gg[i][pre[i]] > w) g[num[i][pre[i]]][k] = gg[i][pre[i]] - w ; for (i = v ; i != par ; i = pre[i]) if (gg[i][pre[i]] > w) g[num[i][pre[i]]][k] = gg[i][pre[i]] - w ; } void Readin () { int i , u , v ,w ; scanf ("%d%d" , &n , &m) ; size = max (n - 1 , m - n + 1) ; memset (num , 0 , sizeof (num)) ; memset (gg , 0 , sizeof (gg)) ; memset (g , 0 , sizeof (g)) ; memset (pre , 0 , sizeof (pre)) ; memset (link , -1 , sizeof (link)) ; memset (x , 0 , sizeof (x)) , memset (y , 0 , sizeof (y)) ; for (i = 1 ; i < n ; i ++) { scanf ("%d%d%d" , &u , &v , &w) ; gg[u][v] = gg[v][u] = x[i] = w ; num[u][v] = num[v][u] = i ;//记录边的序号 } pre[1] = -1 , depth[1] = 0 ; DFS (1 , 1) ; for (i = 1 ; i <= m - n + 1 ; i ++) { scanf ("%d%d%d" , &u , &v , &w) ; y[i] = w ; BuildGraph (i , u , v , w) ; } } bool Find (int i) { l[i] = true ; for (int j = 1 ; j <= size ; j ++) if (!r[j] && lx[i] + ly[j] == g[i][j]) { r[j] = true ; if (link[j] == -1 || Find (link[j])) { link[j] = i ; return true ; } } return false ; } void Adjust () { int i , j , d = INF ; for (i = 1 ; i <= size ; i ++) if (l[i]) { for (j = 1 ; j <= size ; j ++) if (!r[j]) d = min (d , lx[i] + ly[j] - g[i][j]) ; } for (i = 1 ; i <= size ; i ++) { if (l[i]) lx[i] -= d ; if (r[i]) ly[i] += d ; } } void KM () { int i , j ; memset (lx , 0 , sizeof (lx)) ; memset (ly , 0 , sizeof (ly)) ; for (i = 1 ; i <= size ; i ++) for (j = 1 ; j <= size ; j ++) lx[i] = max (lx[i] , g[i][j]) ; for (i = 1 ; i <= size ; i ++) { memset (l , false , sizeof (l)) ; memset (r , false , sizeof (r)) ; while (!Find (i)) { Adjust () ; memset (l , false , sizeof (l)) ; memset (r , false , sizeof (r)) ; } } } void Print () { int i ; for (i = 1 ; i <= size ; i ++) x[link[i]] -= lx[link[i]] , y[i] += ly[i] ; for (i = 1 ; i < n ; i ++) printf ("%d/n" , x[i]) ; for (i = 1 ; i <= m - n + 1 ; i ++) printf ("%d/n" , y[i]) ; } int main () { Readin () ; KM () ; Print () ; return 0 ; }