首页 > 代码库 > HDU 4862 Jump(最小K路径覆盖)

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\n",-cost);112         else puts("-1");113     }114     return 0;115 }
View Code