HDU 4862 Jump(最小K路径覆盖)

输入一个n×m网格图,每个结点的值为0~9,可以从任意点出发不超过k次,走完每个点且仅访问每个结点一次,问最终的能量最大值。不可全部走完的情况输出-1.

初始能量为0。 而结点(x,y)可以跳跃到结点(x,y+dy)或(x+dx,y)。消耗能量为跳跃前后结点的曼哈顿距离 - 1 。若跳跃前后的结点的值相等,能量加上那个值。

具体建图可以参考这里http://blog.sina.com.cn/s/blog_6bddecdc0102uy9g.html

最小K路径覆盖其实在之前是见过的打过的,不过这次又不会了,说明之前不牢固。。。要认真点,没什么时间浪费了。

平时在求二分图的无权的最小覆盖的时候,用的就是 n - 最大匹配

那个从源点连流量为K,费用为0的边到的“那个结点”,实际上就上虚拟前驱。。。因为X集合其实就是Y集合的前驱。而起点的前驱就是没有前驱,即“那个结点”。

然后如果满流量的话,说明所有结点都走了一遍。

模板是找JM伙伴要的。。。据说伙伴是参考KH师兄的=。=

其实最近经常问JM题。。。感觉自己退步了=。=要加油!!!

  1 #include<cstdio>
  2 #include<set>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<algorithm>
  8 #include<queue>
  9 #include<cmath>
 10 using namespace std;
 11 
 12 
 13 #define maxn 222
 14 #define maxe 30000
 15 #define inf 0x3f3f3f3f
 16 
 17 struct Edge{
 18     int u, v, nxt, cap, cost;
 19 }edge[maxe];
 20 int head[maxn];
 21 
 22 struct MinCostMaxFlow{
 23     queue<int> que;
 24     int add; // edges number
 25     int vn; // total vertex number
 26     int cost[maxn], in[maxn], pre[maxn];
 27     bool vis[maxn];
 28     void init(int sz){
 29         add = 0; vn = sz + 10; memset(head, -1, sizeof(head));
 30         while (!que.empty()) que.pop();
 31     }
 32     void insert(int u, int v, int w, int c){// u, v, capacity, cost
 33         edge[add].u = u; edge[add].v = v; edge[add].cap = w; edge[add].cost = c;
 34         edge[add].nxt = head[u]; head[u] = add++;
 35         edge[add].u = v; edge[add].v = u; edge[add].cap = 0; edge[add].cost = -c;
 36         edge[add].nxt = head[v]; head[v] = add++;
 37     }
 38     bool spfa(int s, int e){
 39         memset(cost, 0x3f3f3f3f, sizeof(cost));
 40         memset(in, 0, sizeof(in));
 41         memset(vis, 0, sizeof(vis));
 42         cost[s] = 0; pre[s] = -1;
 43         que.push(s); vis[s] = true; in[s]++;
 44         while (!que.empty()){
 45             int u = que.front(); que.pop();
 46             vis[u] = false;
 47             for (int i = head[u]; i != -1; i = edge[i].nxt){
 48                 int v = edge[i].v;
 49                 if (edge[i].cap > 0 && cost[v] > cost[u] + edge[i].cost){
 50                     cost[v] = cost[u] + edge[i].cost; pre[v] = i;
 51                     if (!vis[v]){
 52                         que.push(v); vis[v] = true; in[v]++;
 53                         if (in[v] > vn) return false;
 54                     }
 55                 }
 56             }
 57         }
 58         return cost[e] < inf;
 59     }
 60     void mincostmaxflow(int s, int e, int &mincost, int &maxflow){
 61         mincost = 0, maxflow = 0;
 62         while (spfa(s, e)){
 63             int flow = inf;
 64             for (int i = pre[e]; i != -1; i = pre[edge[i].u]){
 65                 flow = min(flow, edge[i].cap);
 66             }
 67             maxflow += flow;
 68             for (int i = pre[e]; i != -1; i = pre[edge[i].u]){
 69                 edge[i].cap -= flow;
 70                 edge[i ^ 1].cap += flow;
 71             }
 72             mincost += cost[e] * flow;
 73         }
 74     }
 75 }net;
 76 
 77 int nm;
 78 char ch[22][22];
 79 int main(){
 80     int t,n,m,k,ca=0;
 81     scanf("%d",&t);
 82     while(t--){
 83         scanf("%d%d%d",&n,&m,&k);
 84         nm = n*m;
 85         for(int i=0;i<n;++i)scanf("%s",ch[i]);
 86         net.init(nm*2+3);
 87         for(int i=0;i<n;++i){
 88             for(int j=0;j<m;++j){
 89                 int u = i*m+j+1;
 90                 for(int k=i+1;k<n;++k){
 91                     int v = k*m+j+1;
 92                     int tmp = -(k-i-1);
 93                     if(ch[i][j]==ch[k][j]) tmp+=ch[i][j]-'0';
 94                     net.insert(u,nm+v,1,-tmp);
 95                 }
 96                 for(int k=j+1;k<m;++k){
 97                     int v = i*m+k+1;
 98                     int tmp = -(k-j-1);
 99                     if(ch[i][j]==ch[i][k]) tmp+=ch[i][j]-'0';
100                     net.insert(u,nm+v,1,-tmp);
101                 }
102             }
103         }
104         for(int i=nm+1;i<=nm*2;++i) net.insert(nm*2+1,i,1,0);
105         for(int i=1;i<=nm;++i) net.insert(0,i,1,0);
106         net.insert(0,nm*2+1,k,0);
107         for(int i=nm+1;i<=nm*2;++i)net.insert(i,nm*2+2,1,0);
108         int cost,flow;
109         net.mincostmaxflow(0,nm*2+2,cost,flow);
110         printf("Case %d : ",++ca);
111         if(flow==nm) printf("%d
",-cost);
112         else puts("-1");
113     }
114     return 0;
115 }
View Code
原文地址:https://www.cnblogs.com/nextbin/p/3863911.html