题意:有n个城市, m条单向路, 这个路有长度, 现在需要将这n个城市分成几个环, 这几个环不能有相交的城市, 求出最小的总长度。
题解:在一个单项环中,每个城市都只会被一条路指到,所以用KM算法跑出最小费用就好了。
注意的就是题目会给出重边。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 110; 18 int val[N][N]; 19 int lx[N], ly[N], match[N]; 20 int visx[N], visy[N]; 21 int slack[N]; 22 int n, m; 23 void init(){ 24 memset(match, -1, sizeof(match)); 25 memset(ly, 0, sizeof(ly)); 26 //memset(lx, -inf, sizeof(lx)); 27 //memset(val, -inf, sizeof(val)); 28 for(int i = 1; i <= n; i++){ 29 lx[i] = -inf; 30 for(int j = 1; j <= n; j++) 31 val[i][j] = -inf; 32 } 33 34 } 35 bool hunger(int u){ 36 visx[u] = 1; 37 for(int i = 1; i <= n; i++){ 38 if(visy[i] || val[u][i] == -inf) continue; 39 else { 40 if(lx[u] + ly[i] == val[u][i]){ 41 visy[i] = 1; 42 if(match[i] == -1 || hunger(match[i])){ 43 match[i] = u; 44 return true; 45 } 46 } 47 else slack[i] = min(slack[i], lx[u]+ly[i] - val[u][i]); 48 } 49 } 50 return false; 51 52 } 53 int KM_perferct_match(){ 54 /*for(int i = 1; i <= n; i++) 55 for(int j = 1; j <= n; j++) 56 if(val[i][j] != -inf) 57 lx[i] = max(lx[i], val[i][j]);*/ 58 for(int i = 1; i <= n; i++){ 59 memset(slack, inf, sizeof(slack)); 60 while(1){ 61 memset(visx, 0, sizeof(visx)); 62 memset(visy, 0, sizeof(visy)); 63 if(hunger(i)) break; 64 else { 65 int tmp = inf; 66 for(int j = 1; j <= n; j++) 67 if(!visy[j]) tmp = min(tmp, slack[j]); 68 if(tmp == inf) return 1; 69 for(int j = 1; j <= n; j++){ 70 if(visx[j]) lx[j] -= tmp; 71 if(visy[j]) ly[j] += tmp; 72 } 73 } 74 } 75 } 76 int ans = 0; 77 for(int i = 1; i <= n; i++) 78 if(match[i] != -1) ans += val[match[i]][i]; 79 return ans; 80 } 81 int main(){ 82 while(~scanf("%d%d", &n, &m)){ 83 init(); 84 while(m--){ 85 int a, b, c; 86 scanf("%d%d%d", &a, &b, &c); 87 val[a][b] = max(val[a][b], -c); 88 lx[a] = max(lx[a], val[a][b]); 89 } 90 printf("%d ", -KM_perferct_match()); 91 } 92 return 0; 93 }
emm, 第一次知道, memset(a, -inf, sizeof(a)) 后 a[0] != -inf;