pku 3422 Kaka's Matrix Travels最大費用最大ストリーム
3086 ワード
http://poj.org/problem?id=3422
/*
标题:n*nの矩形の四角い格子を与えて、(1,1)から右下にしか歩けないことを要求して、(i+1,j)あるいは(i+n,j)歩き終わるたびに格子の中の数を累積して、歩いた格子の中の数をゼロにして、kが得られる最大の数を聞く.
*/
/*
ネットの流れのテーマの建図は肝心で、このテーマの建図はとても考えにくいです!まず取り外します.ここでは1つの点を2つの点に分割し、2つのエッジを確立し、1つは流量が1になり、重み値はmap[i][j]、もう1つは流量が無限で、重み値が0になった.注意この辺は、この店を通った後、map[i][j]が0になった後も、流量があり、重み値が0であることを保証するため、右下に流量が無限の重み値が0であることを確立するための辺である.最後に確立するのはスーパーソース点と汇点の辺で、すべて流量がkの重み値が0の辺で、k回歩くことを保証します.
*/
code:
/*
标题:n*nの矩形の四角い格子を与えて、(1,1)から右下にしか歩けないことを要求して、(i+1,j)あるいは(i+n,j)歩き終わるたびに格子の中の数を累積して、歩いた格子の中の数をゼロにして、kが得られる最大の数を聞く.
*/
/*
ネットの流れのテーマの建図は肝心で、このテーマの建図はとても考えにくいです!まず取り外します.ここでは1つの点を2つの点に分割し、2つのエッジを確立し、1つは流量が1になり、重み値はmap[i][j]、もう1つは流量が無限で、重み値が0になった.注意この辺は、この店を通った後、map[i][j]が0になった後も、流量があり、重み値が0であることを保証するため、右下に流量が無限の重み値が0であることを確立するための辺である.最後に確立するのはスーパーソース点と汇点の辺で、すべて流量がkの重み値が0の辺で、k回歩くことを保証します.
*/
code:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#define maxn 5005
using namespace std;
const int inf = 99999999;
struct node
{
int u,v;
int c,w;
int next;
}g[maxn*100];
int head[maxn],cnt,pre[maxn];
int dis[maxn],map[maxn][maxn];
bool inq[maxn];
int n,m,k,s,t,ans;
//
void init()
{
memset(head,-1,sizeof(head));
cnt = 0;
}
// ,
void add(int u,int v,int c,int w)
{
g[cnt].u = u; g[cnt].v = v; g[cnt].c = c; g[cnt].w = w;
g[cnt].next = head[u]; head[u] = cnt++;
g[cnt].u = v; g[cnt].v = u; g[cnt].c = 0; g[cnt].w = -w;
g[cnt].next = head[v]; head[v] = cnt++;
}
void spfa()
{
int i;
queue<int>q;
for (i = 0; i <= t; ++i)
{
dis[i] = -inf;
inq[i] = false;
pre[i] = -1;
}
q.push(s); inq[s] = true;
dis[s] = 0;
while (!q.empty())
{
int u = q.front(); q.pop();
inq[u] = false;
for (i = head[u]; i != -1; i = g[i].next)
{
int v = g[i].v;
if (g[i].c && dis[v] < dis[u] + g[i].w)
{
dis[v] = dis[u] + g[i].w;
pre[v] = i;//
if (!inq[v])
{
inq[v] = true;
q.push(v);
}
}
}
}
}
void MCMF()
{
while (1)
{
spfa();
if (pre[t] == -1) break;
int x = t,minf = inf;
while (x != s)
{
minf = min(minf,g[pre[x]].c);
x = g[pre[x]].u;
}
x = t;
while (x != s)
{
g[pre[x]].c -= minf;
g[pre[x]^1].c += minf;
x = g[pre[x]].u;
}
ans += minf*dis[t];
}
}
int main()
{
int i,j;
scanf("%d%d",&n,&k);
int tmp = n*n;
init();
//
for (i = 1; i <= n; ++i)
{
for (j = 1; j <= n; ++j)
{
scanf("%d",&map[i][j]);
int x = (i - 1)*n + j;
int y = x + tmp;
add(x,y,1,map[i][j]);
add(x,y,inf,0);
if (i < n) add(y,x + n,inf,0);
if (j < n) add(y,x + 1,inf,0);
}
}
s = 0; t = 2*tmp + 1;
add(s,1,k,0);
add(2*tmp,t,k,0);
ans = 0;
MCMF();
printf("%d
",ans);
return 0;
}