感觉网络流的问题 大部分都是考建图, 建图的时候又经常拆点来限流。这道题目建图比较简单,很适合学习用~~~
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <cmath>
#include <algorithm>
#define fr(i,s,n) for(int i=s;i<n;++i)
#define _fr(i,n,s) for(int i=n-1;i>=s;--i)
#define fi freopen("in.txt","r",stdin)
#define cl(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll; typedef double dl;
const int inf = 0xffffff;
#define M 200001
#define maxx 2000
class Mcmf{
public:
struct T{
int from, to, val;
int next, cost;
}edge[M];
int len;
int visit[M], pre[M], dist[M], que[M], vis[M], pos[M];
void init(){
memset(vis,-1,sizeof(vis));
len=0;
}
void add(int from, int to, int val, int cost)
{
edge[len].from = from,edge[len].to = to, edge[len].val = val, edge[len].cost = cost;
edge[len].next = vis[from], vis[from] = len++;
edge[len].from = to, edge[len].to = from, edge[len].val = 0, edge[len].cost = -cost;
edge[len].next = vis[to], vis[to] = len++;
}
int SPFA(int s, int t, int n)
{
int i, to, k;
for (i = 0; i <= n; i++){
pre[i] = -1, visit[i] = 0;
}
int head, tail;
head = tail = 0;
for (i = 0; i <= n; i++)
dist[i] = -1;//求最小费用时这里得改成正无穷
que[tail++] = s, pre[s] = s, dist[s] = 0, visit[s] = 1;
while (head != tail){
int from = que[head++];
visit[from] = 0;
for (k = vis[from]; k != -1; k = edge[k].next){
to = edge[k].to;
if (edge[k].val > 0 && dist[from]+edge[k].cost > dist[to]){//最大费用,求最小费用时这里的改符号
dist[to] = dist[from] + edge[k].cost;
pre[to] = from;
pos[to] = k;
if (!visit[to]){
visit[to] = 1;
que[tail++] = to;
}
}
}
}
if (pre[t] != -1 && dist[t] >-1)//求最小费用时这里改成dit[t] < 正无穷
return 1;
return 0;
}
int mnCostFlow(int s, int t, int n)
{
if (s == t){
//这里具体情况具体分析,如果有附加s跟t就不用,如果用数据中的点作为s跟t就得考虑
//直接返回某个值。否则SPFA里的队列会死循环。
}
int flow = 0, cost = 0;
while (SPFA(s, t, n)){
int from, mn = inf;
for (from = t; from != s; from = pre[from])
mn = min(mn, edge[pos[from]].val);
flow += mn;
cost += dist[t] * mn;
for (from = t; from != s; from = pre[from]){
edge[pos[from]].val -= mn;
edge[pos[from]^1].val += mn;
}
}
return cost;
}
}mcf;
int N,K;
int map[1010][1010];
void build (){
int n = N*N;
int x;
fr(i , 0 ,N){
fr(j , 0, N){
x = i * N + j;
mcf.add(x ,x+n ,1 ,map[i][j] );
mcf.add(x , x+n, K, 0);
if ( i+1< N) mcf.add( x + n, x +N, inf ,0);
if (j+1<N) mcf.add(x+n,x+1,inf,0);
}
}
int s = n<<1,t = s+1;
mcf.add(s , 0, K,0);
mcf.add(s-1 ,t, K, 0);
int ans = mcf.mnCostFlow(s,t,t+1);
printf("%d\n",ans);
}
int main(){
while(scanf("%d%d",&N,&K)!=EOF){
cl(map);
mcf.init();
fr(i,0,N)
fr(k,0,N){
scanf("%d",&map[i][k]);
}
build();
}
return 0;
}
427

被折叠的 条评论
为什么被折叠?



