POJ 3422 Kaka's Matrix Travels

这题的费用流模型应该很明显,已知从起点开始一共可以走k次,那么容量就有了。

对每个点,把他拆成(i,i'),因为点上的权只能取一次,以后再经过这个点的时候,权值为0,所以这里就对应了两条边(i,i',1,-w),(i,i',k-1,0)。

另外,对于所有i点能够到达的点j,对应一条边(i',j,k,0)。

跑一遍最小费用流再取反即为结果。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <queue>
 5 #define maxn 5010
 6 #define maxm 100010
 7 #define INF 1<<30
 8 using namespace std;
 9 struct MCMF{
10     int src,sink,e,n;
11     int first[maxn];
12     int cap[maxm],cost[maxm],v[maxm],next[maxm];
13     bool flag;
14     void init(){
15         e = 0;
16         memset(first,-1,sizeof(first));
17     }
18 
19     void add_edge(int a,int b,int cc,int ww){
20         //printf("add:%d to %d,cap = %d,cost = %d
",a,b,cc,ww);
21         cap[e] = cc;cost[e] = ww;v[e] = b;
22         next[e] = first[a];first[a] = e++;
23         cap[e] = 0;cost[e] = -ww;v[e] = a;
24         next[e] = first[b];first[b] = e++;
25     }
26 
27     int d[maxn],pre[maxn],pos[maxn];
28     bool vis[maxn];
29 
30     bool spfa(int s,int t){
31         memset(pre,-1,sizeof(pre));
32         memset(vis,0,sizeof(vis));
33         queue<int> Q;
34         for(int i = 0;i <= n;i++)   d[i] = INF;
35         Q.push(s);pre[s] = s;d[s] = 0;vis[s] = 1;
36         while(!Q.empty()){
37             int u = Q.front();Q.pop();
38             vis[u] = 0;
39             for(int i = first[u];i != -1;i = next[i]){
40                 if(cap[i] > 0 && d[u] + cost[i] < d[v[i]]){
41                     d[v[i]] = d[u] + cost[i];
42                     pre[v[i]] = u;pos[v[i]] = i;
43                     if(!vis[v[i]])  vis[v[i]] = 1,Q.push(v[i]);
44                 }
45             }
46         }
47         return pre[t] != -1;
48     }
49 
50     int Mincost;
51     int Maxflow;
52 
53     int MinCostFlow(int s,int t,int nn){
54         Mincost = 0,Maxflow = 0,n = nn;
55         while(spfa(s,t)){
56             int min_f = INF;
57             for(int i = t;i != s;i = pre[i])
58                 if(cap[pos[i]] < min_f) min_f = cap[pos[i]];
59             Mincost += d[t] * min_f;
60             Maxflow += min_f;
61             for(int i = t;i != s;i = pre[i]){
62                 cap[pos[i]] -= min_f;
63                 cap[pos[i]^1] += min_f;
64             }
65         }
66         return Mincost;
67     }
68 };
69 MCMF g;
70 int N,K;
71 int id(int a,int b){
72     return (a-1)*N + b;
73 }
74 int main(){
75     while(scanf("%d%d",&N,&K) == 2){
76         g.init();
77         int nt = N*N;
78         for(int i = 1;i <= N;i++)
79             for(int j = 1;j <= N;j++){
80                 int a;
81                 scanf("%d",&a);
82                 g.add_edge(id(i,j),id(i,j)+nt,1,-a);
83                 g.add_edge(id(i,j),id(i,j)+nt,K-1,0);
84                 if(i < N)   g.add_edge(id(i,j)+nt,id(i+1,j),K,0);
85                 if(j < N)   g.add_edge(id(i,j)+nt,id(i,j+1),K,0);
86             }
87         int src = 0,sink = nt*2+1;
88         g.add_edge(src,1,K,0);
89         g.add_edge(nt*2,sink,K,0);
90         printf("%d
",-g.MinCostFlow(src,sink,sink));
91     }
92     return 0;
93 }
View Code
原文地址:https://www.cnblogs.com/zhexipinnong/p/3358452.html