HDU 4862 Jump 任意起点最大权K链不相交覆盖
你可以从任意起点开始起跳最多K次
每次跳你可以选择往右或者往下跳 从(x1,y1)跳到(x2,y2) 消耗的能量是曼哈顿距离-1
但是如果每次跳的起点和终点格子里的数字是相同的为X的话你会得到X能量
问你跳K次能不能把整个图刚好跳完(每个点被经过一次) 如果可以的话输出能量的最大值
解:和最小链覆盖一样先把每个点拆成入点和出点 左边是出点 右边是入点 然后按照题意建好边
重要的是我们怎么限制最多起跳K次这个条件 解决方法是Add(S,S',K,0) 然后S'朝右边每个点连一条容量为1费用为0的边
为什么这样就是最多K条链呢?考虑最小链覆盖=|V|-匹配数 即匹配完后 右边没有被匹配的点(入点)是要被当作一条链的起点的 所以右边有几个没被匹配的点就要有几条链
所以我们限制右边最多只能有K个节点没被匹配到即可
#include<bits/stdc++.h> #define reg register using namespace std; typedef long long ll; typedef int JQK; const int INF = 0x7f7f7f7f; const int MAXN = 505, MAXM = 13000; int Head[MAXN], cur[MAXN], to[MAXM << 1], nxt[MAXM << 1], f[MAXM << 1], ed = 1; int S, T, MAXP, MAXF, pre[MAXN]; JQK lev[MAXN], mono[MAXM << 1]; bool exist[MAXN]; inline void RR(int &x) { char c; bool sign = false; for (c = getchar(); c < '0' || c > '9'; c = getchar()) if (c == '-') { sign = true; } for (x = 0; c >= '0' && c <= '9'; c = getchar()) { x = x * 10 + c - '0'; } sign && (x = -x); }char f1[15][15]; int ff[15][15]; int num[15][15]; int main() { int TNT; int n, m, K; RR(TNT); for (int cas = 1; cas <= TNT; cas++) { int sum = 0; RR(n), RR(m), RR(K); for (int i = 1; i <= n; i++) { scanf("%s", f1[i] + 1); for (int j = 1; j <= m; j++) { ff[i][j] = f1[i][j] - '0'; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { num[i][j] = ++sum; } } MAXP = 2 * sum + 3; init(2 * sum + 2, 2 * sum + 3); addedge(S, S - 1, K, 0); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { addedge(S, num[i][j], 1, 0); addedge(sum + num[i][j], T, 1, 0); addedge(S - 1, sum + num[i][j], 1, 0); } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { int now = ff[i][j]; for (int k = i + 1; k <= n; k++) { int now2 = ff[k][j]; int add = (now == now2) ? now : 0; addedge(num[i][j], sum + num[k][j], 1, -(add - (k - i - 1))); } for (int k = j + 1; k <= m; k++) { int now2 = ff[i][k]; int add = (now == now2) ? now : 0; addedge(num[i][j], sum + num[i][k], 1, -(add - (k - j - 1))); } } } printf("Case %d : ", cas); if (K < min(n, m)) { printf("-1\n"); continue; } int anser = MCMF(); if (MAXF != sum) { printf("-1\n"); } else { printf("%d\n", -anser); } } return 0; }