http://poj.org/problem?id=3422
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <queue> 5 using namespace std; 6 const int INF = 1<<28; 7 const int N=50050; 8 int Map[55][55],dis[N]; 9 int head[N],pre[N]; 10 bool vis[N]; 11 int cnt = 0; 12 int ans = 0; 13 int n; 14 struct node 15 { 16 int u,v,c,f; 17 int next; 18 19 } edge[N]; 20 void add(int u,int v,int c,int f) 21 { 22 edge[cnt].u = u; 23 edge[cnt].v = v; 24 edge[cnt].c = c; 25 edge[cnt].f = f; 26 edge[cnt].next = head[u]; 27 head[u] = cnt++; 28 edge[cnt].u = v; 29 edge[cnt].v = u; 30 edge[cnt].c = -c; 31 edge[cnt].f = 0; 32 edge[cnt].next = head[v]; 33 head[v] = cnt++; 34 } 35 int spfa() 36 { 37 for (int i = 0; i <= n*n*2+1; i++) 38 { 39 dis[i] = INF; 40 pre[i] = -1; 41 vis[i] = false; 42 } 43 dis[n*n*2] = 0; 44 queue<int>q; 45 q.push(n*n*2); 46 vis[n*n*2] = true; 47 while(!q.empty()) 48 { 49 int u = q.front(); 50 vis[u] = false; 51 q.pop(); 52 for (int j = head[u]; j!=-1; j=edge[j].next) 53 { 54 if (edge[j].f > 0&&dis[edge[j].v] > dis[u]+ edge[j].c) 55 { 56 pre[edge[j].v] = j; 57 dis[edge[j].v] = dis[u]+ edge[j].c; 58 if (!vis[edge[j].v]) 59 { 60 q.push(edge[j].v); 61 vis[edge[j].v] = true; 62 } 63 } 64 } 65 } 66 if (pre[n*n*2+1]==-1) 67 return 0; 68 return 1; 69 } 70 void MCMF() 71 { 72 while(spfa()) 73 { 74 int Minflow = INF; 75 int j = pre[n*n*2+1]; 76 while(j!=-1) 77 { 78 Minflow = min(Minflow,edge[j].f); 79 j = pre[edge[j].u]; 80 } 81 j = pre[n*n*2+1]; 82 while(j!=-1) 83 { 84 edge[j].f-=Minflow; 85 edge[j^1].f+=Minflow; 86 ans+=Minflow*edge[j].c; 87 j = pre[edge[j].u]; 88 } 89 } 90 } 91 int main() 92 { 93 int k; 94 scanf("%d%d",&n,&k); 95 memset(Map,0,sizeof(Map)); 96 memset(head,-1,sizeof(head)); 97 for (int i = 1; i <= n; i++) 98 { 99 for (int j = 1; j <= n; j++) 100 { 101 scanf("%d",&Map[i][j]); 102 } 103 } 104 for (int i = 1; i <= n; i++)//拆点 105 { 106 for (int j = 1; j <= n; j++) 107 { 108 int u = (i-1)*n+j-1; 109 add(2*u,2*u+1,-Map[i][j],1);//加边 110 add(2*u,2*u+1,0,k-1); 111 } 112 } 113 for (int i = 1; i <= n; i++)//向右加边 114 { 115 for (int j = 1; j < n; j++) 116 { 117 int u = (i-1)*n+j-1; 118 add(2*u+1,(u+1)*2,0,k); 119 } 120 } 121 for (int i = 1; i < n; i++)//向下加边 122 { 123 for (int j = 1; j <= n; j++) 124 { 125 int u = (i-1)*n+j-1; 126 add(2*u+1,(u+n)*2,0,k); 127 } 128 } 129 add(n*n*2,0,0,k);//加源点 130 add(n*n*2-1,n*n*2+1,0,k);//加终点 131 MCMF(); 132 printf("%d ",-ans); 133 return 0; 134 }