Tour HDU - 3488
Tour
可以用费用流做
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf = 0x3f3f3f3f; 4 const int maxv = 410; 5 const int maxe = maxv * maxv; 6 7 struct Edge{ 8 int u, v, cap, flow, cost; 9 int nxt; 10 Edge(int u = 0, int v = 0, int cap = 0, int flow = 0, int cost = 0, int nxt = 0) : 11 u(u), v(v), cap(cap), flow(flow), cost(cost), nxt(nxt) {} 12 }e[maxe << 1]; 13 14 int head[maxv]; 15 int cnt; 16 void init(){ 17 cnt = 0; 18 memset(head, -1, sizeof head); 19 } 20 21 void add(int u, int v, int cap, int cost){ 22 e[cnt] = Edge(u, v, cap, 0, cost, head[u]); 23 head[u] = cnt++; 24 e[cnt] = Edge(v, u, 0, 0, -cost, head[v]); 25 head[v] = cnt++; 26 } 27 28 int N; 29 int d[maxv], p[maxv], a[maxv], inq[maxv]; 30 bool BellmanFord(int s, int t, int &flow, int &cost){ 31 for(int i = 0; i < N; i++) d[i] = inf; 32 memset(inq, 0, sizeof inq); 33 d[s] = 0, a[s] = inf, p[s] = 0, inq[s] = 1; 34 queue<int> q; 35 q.push(s); 36 while(!q.empty()){ 37 int u = q.front(); 38 q.pop(); 39 inq[u] = 0; 40 for(int i = head[u]; ~i; i = e[i].nxt){ 41 Edge &tp = e[i]; 42 if(tp.cap > tp.flow && d[tp.v] > d[u] + tp.cost){ 43 d[tp.v] = d[u] + tp.cost; 44 p[tp.v] = i; 45 a[tp.v] = min(a[u], tp.cap - tp.flow); 46 if(!inq[tp.v]){ 47 q.push(tp.v); 48 inq[tp.v] = 1; 49 } 50 } 51 } 52 } 53 if(d[t] == inf) return false; 54 flow += a[t]; 55 cost += a[t] * d[t]; 56 int u = t; 57 while(u != s){ 58 e[p[u]].flow += a[t]; 59 e[p[u] ^ 1].flow -= a[t]; 60 u = e[p[u]].u; 61 } 62 return true; 63 } 64 65 66 int MCMF(int s, int t){ 67 int flow = 0, cost = 0; 68 while(BellmanFord(s, t, flow, cost)); 69 return cost; 70 } 71 72 int gra[maxv<<1][maxv<<1]; 73 int main(){ 74 int t; 75 scanf("%d", &t); 76 while(t--){ 77 memset(gra, inf, sizeof(gra)); 78 init(); 79 int n, m; 80 scanf("%d %d", &n, &m); 81 int u, v, w; 82 for(int i = 0; i < m; i++){ 83 scanf("%d %d %d", &u, &v, &w); 84 gra[u * 2 + 1][v * 2] = min(gra[u * 2 + 1][v * 2], w); 85 } 86 for(int i = 2; i <= n * 2 + 1; i++){ 87 for(int j = 2; j <= n * 2 + 1; j++){ 88 if(gra[i][j] != inf) add(i, j, 1, gra[i][j]); 89 } 90 } 91 int S = 0, T = 1; 92 N = 2 * n + 2; 93 for(int i = 1; i <= n; i++){ 94 add(S, i * 2 + 1, 1, 0); 95 add(i * 2, T, 1, 0); 96 } 97 printf("%d\n", MCMF(S, T)); 98 } 99 return 0; 100 }
也可以用KM
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxv=210; 4 const int inf=0x3f3f3f3f; 5 6 int vb[maxv],vg[maxv],eb[maxv],eg[maxv]; 7 int c[maxv][maxv]; 8 int slack[maxv]; 9 int mc[maxv]; 10 #define CLR(m,a) memset(m,a,sizeof(m)) 11 int n,m; 12 int dfs(int x) 13 { 14 vg[x]=1; 15 for(int i=0;i<n;i++) 16 { 17 if(vb[i]) continue; 18 int gap=eg[x]+eb[i]-c[x][i]; 19 if(gap==0) 20 { 21 vb[i]=1; 22 if(mc[i]==-1||dfs(mc[i])) 23 { 24 mc[i]=x; 25 return 1; 26 } 27 } 28 else slack[i]=min(slack[i],gap); 29 } 30 return 0; 31 } 32 int KM() 33 { 34 CLR(mc,-1); 35 CLR(eb,0); 36 for(int i=0;i<n;i++) 37 { 38 eg[i]=c[i][0]; 39 for(int j=1;j<n;j++) 40 eg[i]=max(eg[i],c[i][j]); 41 } 42 for(int i=0;i<n;i++) 43 { 44 CLR(slack,inf); 45 while(1) 46 { 47 CLR(vb,0); 48 CLR(vg,0); 49 if(dfs(i)) break; 50 int d=inf; 51 for(int i=0;i<n;i++) if(!vb[i]) d=min(d,slack[i]); 52 for(int i=0;i<n;i++) 53 { 54 if(vg[i]) eg[i]-=d; 55 if(vb[i]) eb[i]+=d; 56 else slack[i]-=d; 57 } 58 } 59 } 60 int ans=0; 61 for(int i=0;i<n;i++) 62 { 63 if(mc[i]==-1) return -1; 64 if(c[mc[i]][i]==-inf) return -1; 65 ans+=c[mc[i]][i]; 66 } 67 return -ans; 68 } 69 int main() 70 { 71 int t; 72 scanf("%d",&t); 73 while(t--) 74 { 75 scanf("%d%d",&n,&m); 76 int u,v,w; 77 for(int i=0;i<n;i++) 78 for(int j=0;j<n;j++) c[i][j]=-inf; 79 for(int i=0;i<m;i++) 80 { 81 scanf("%d%d%d",&u,&v,&w); 82 u--;v--; 83 c[u][v]=max(-w,c[u][v]); 84 } 85 printf("%d\n",KM()); 86 } 87 }
不同的是建图的时候的区别,费用流要拆点,而KM不用,因为KM左右两边的点已经视为不同了。
这个题还要注意有重边,费用流盲目建图会TLE。