关键在于建图,昨天做的的时候直接想错了。放了放,在路上和gyx讨论了一下,他说是不是拆点,我一想真是啊。。。
然后想了想建图的细节。。。今天写了程序,居然把电脑给写挂了。。第一次啊,可见程序写的多不靠谱啊。。
把一个点拆成两个点,这两个点之间的流量为1,费用为权值,这条边的起点和终点都可以连接下个位置的起点。
为了控制流量,多加了k个点,这多出来的k个点,到终点的流量为1,来控制最终的流量。剩下的就是模版了,改了一下求最大。
这样建图效率不是很高,想会不会超时。。。果真TLE了,不过数组开小了,开大之后,水过400+ms。。。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <queue> 5 using namespace std; 6 #define INF 0x7fffffff 7 8 int p[51][51]; 9 10 int low[6001],path[6001]; 11 int first[6001],in[6001],dis[6001]; 12 int str,end,t; 13 struct node 14 { 15 int u,v,w,cost,re,next; 16 }edge[900001]; 17 int ans; 18 void CL() 19 { 20 t = 1; 21 memset(first,-1,sizeof(first)); 22 } 23 void add(int u,int v,int w,int cost) 24 { 25 edge[t].u = u; 26 edge[t].v = v; 27 edge[t].w = w; 28 edge[t].cost = cost; 29 edge[t].re = t+1; 30 edge[t].next = first[u]; 31 first[u] = t ++; 32 33 edge[t].u = v; 34 edge[t].v = u; 35 edge[t].w = 0; 36 edge[t].cost = -cost; 37 edge[t].re = t-1; 38 edge[t].next = first[v]; 39 first[v] = t ++; 40 } 41 int bfs() 42 { 43 int u,i,v; 44 memset(path,-1,sizeof(path)); 45 for(i = 0;i <= end;i ++) 46 { 47 dis[i] = -INF; 48 in[i] = 0; 49 } 50 queue<int>que; 51 que.push(str); 52 dis[str] = 0; 53 in[str] = 1; 54 low[str] = INF; 55 while(!que.empty()) 56 { 57 u = que.front(); 58 in[u] = 0; 59 que.pop(); 60 for(i = first[u];i != -1;i = edge[i].next) 61 { 62 v = edge[i].v; 63 if(edge[i].w&&dis[v] < dis[u]+edge[i].cost) 64 { 65 dis[v] = dis[u] + edge[i].cost; 66 path[v] = i; 67 low[v] = low[u] < edge[i].w ? low[u]:edge[i].w; 68 if(!in[v]) 69 { 70 que.push(v); 71 in[v] = 1; 72 } 73 } 74 } 75 } 76 if(path[end] == -1) 77 return -1; 78 else 79 return low[end]; 80 81 } 82 void mcmf() 83 { 84 int res,temp,now; 85 while((res = bfs()) != -1) 86 { 87 now = end; 88 while(now != str) 89 { 90 temp = path[now]; 91 edge[temp].w -= res; 92 edge[edge[temp].re].w += res; 93 ans += res*edge[temp].cost; 94 now = edge[temp].u; 95 } 96 } 97 } 98 int main() 99 { 100 int n,i,j,k; 101 int x,y; 102 ans = 0; 103 CL(); 104 scanf("%d %d",&n,&k); 105 for(i = 1;i <= n;i ++) 106 { 107 for(j = 1;j <= n;j ++) 108 scanf("%d",&p[i][j]); 109 } 110 str = 0; 111 end = 2*n*n + k + 1; 112 add(str,1,INF,0); 113 for(i = 1;i <= n;i ++) 114 { 115 for(j = 1;j <= n;j ++) 116 { 117 x = (i-1)*n + j; 118 y = x + n*n; 119 add(x,y,1,p[i][j]); 120 if(i + 1 <= n) 121 { 122 add(x,x+n,INF,0); 123 add(y,x+n,INF,0); 124 } 125 if(j + 1 <= n) 126 { 127 add(x,x+1,INF,0); 128 add(y,x+1,INF,0); 129 } 130 } 131 } 132 for(i = 1;i <= k;i ++) 133 { 134 add(x,2*n*n+i,INF,0); 135 add(y,2*n*n+i,INF,0); 136 add(2*n*n+i,end,1,0); 137 } 138 mcmf(); 139 printf("%d\n",ans); 140 return 0; 141 }