这个题一开始感觉像两条路径和 毕竟求的东西名字都一样
后来发现不行 因为那个是强制限制一条边只能走一次
这个是以后还可以走但是没有价值了
所以考虑一下拆点
不同的地方在于每个点只能走一次有权值的路径
所以拆的点之间建两条边 一条有权值流量为1 一条没权值流量为k-1
然后起点连源 终点连汇 左上右部图连右下左部图都是套路
注意求最大费用 取相反数即可
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<queue> 6 #define ms(a,b) memset(a,b,sizeof a) 7 #define rep(i,a,n) for(int i = a;i <= n;i++) 8 #define per(i,n,a) for(int i = n;i >= a;i--) 9 #define inf 2147483647 10 using namespace std; 11 typedef long long ll; 12 typedef double D; 13 #define eps 1e-8 14 ll read() { 15 ll as = 0,fu = 1; 16 char c = getchar(); 17 while(c < '0' || c > '9') { 18 if(c == '-') fu = -1; 19 c = getchar(); 20 } 21 while(c >= '0' && c <= '9') { 22 as = as * 10 + c - '0'; 23 c = getchar(); 24 } 25 return as * fu; 26 } 27 //head 28 const int N = 10005; 29 const int M = 100005; 30 int s = N-1,t = N-2; 31 int head[N],nxt[M],mo[M],cnt = 1; 32 int cst[M],flw[M]; 33 void _add(int x,int y,int w,int f) { 34 mo[++cnt] = y; 35 nxt[cnt] = head[x]; 36 head[x] = cnt; 37 cst[cnt] = w,flw[cnt] = f; 38 } 39 void add(int x,int y,int f,int w) { 40 if(x^y)_add(x,y,w,f),_add(y,x,-w,0); 41 } 42 43 int dis[N],flow[N]; 44 int pre[N],lst[N]; 45 bool vis[N]; 46 bool spfa() { 47 ms(dis,70),ms(flow,70),ms(vis,0); 48 queue<int> q; 49 q.push(s),pre[t] = dis[s] = 0,vis[s] = 1; 50 while(!q.empty()) { 51 int x = q.front(); 52 q.pop(),vis[x] = 0; 53 for(int i = head[x];i;i = nxt[i]) { 54 int sn = mo[i]; 55 if(dis[sn] > dis[x] + cst[i] && flw[i]) { 56 dis[sn] = dis[x] + cst[i]; 57 pre[sn] = x,lst[sn] = i; 58 flow[sn] = min(flow[x],flw[i]); 59 if(!vis[sn]) vis[sn] = 1,q.push(sn); 60 } 61 } 62 } 63 return pre[t]; 64 } 65 66 int maxx,minn; 67 void MCMF() { 68 maxx = minn = 0; 69 while(spfa()) { 70 maxx += flow[t],minn += dis[t] * flow[t]; 71 int x = t; 72 while(x ^ s) { 73 flw[lst[x]] -= flow[t]; 74 flw[lst[x] ^ 1] += flow[t]; 75 x = pre[x]; 76 } 77 } 78 } 79 80 int n,k; 81 int idx(int x,int y,int f) {return (x-1) * n + y + f * n * n;} 82 83 void build() { 84 n = read(),k = read(); 85 rep(i,1,n) rep(j,1,n) add(idx(i,j,0),idx(i,j,1),1,-read()); 86 rep(i,1,n) rep(j,1,n) add(idx(i,j,0),idx(i,j,1),k-1,0); 87 add(s,idx(1,1,0),k,0); 88 add(idx(n,n,1),t,k,0); 89 rep(i,1,n) rep(j,1,n) { 90 if(i < n) add(idx(i,j,1),idx(i+1,j,0),k,0); 91 if(j < n) add(idx(i,j,1),idx(i,j+1,0),k,0); 92 } 93 } 94 95 int main() { 96 build(),MCMF(),printf("%d ",-minn); 97 return 0; 98 }