给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大
第一行两个数n,k(1<=n<=50, 0<=k<=10)
接下来n行,每行n个数,分别表示矩阵的每个格子的数
一个数,为最大和
3 1
1 2 3
0 2 1
1 4 2
11
1<=n<=50, 0<=k<=10
把每个节点拆成两个,分别为ai和bi
ai向bi连边,费用为权值,容量为1
再连边,费用为0,容量为k,保证联通
其他能到达i号点的点,向ai连边,费用为0,流量为k。向外连边则用bi向外连。
新建节点s向< 1,1 >连边,费用为0,流量为k。
新建节点e向< n,n >连边,费用为0,流量为k。
然后s向e做最大费用流。
然后我想问,为什么我的dinic比EK慢!!dinic会T两个点!!
代码(EK):
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int SZ=100010;
const int INF=1000000000;
int head[SZ],nxt[SZ],tot=1;
struct edge{
int f,t,d,c;
}l[SZ];
void build(int f,int t,int d,int c)
{
l[++tot].t=t;
l[tot].f=f;
l[tot].d=d;
l[tot].c=c;
nxt[tot]=head[f];
head[f]=tot;
}
int s,e,n;
queue<int> q;
int pre[SZ],f[SZ],dist[SZ];
bool use[SZ];
bool spfa(int &cost,int &flow)
{
for(int i=1;i<=n;i++) dist[i]=-INF;
f[s]=INF;
dist[s]=0;
q.push(s);
use[s]=1;
while(q.size())
{
int f=q.front(); q.pop();
use[f]=0;
for(int i=head[f];i;i=nxt[i])
{
int v=l[i].t;
if(l[i].c && dist[v] < dist[f] + l[i].d)
{
dist[v] = dist[f] + l[i].d;
::f[v] = min(::f[f],l[i].c);
pre[v] = i;
if(!use[v])
{
use[v]=1;
q.push(v);
}
}
}
}
if(dist[e]==-INF) return false;
flow += f[e];
cost += dist[e] * f[e];
for(int i=e;i!=s;i=l[pre[i]].f)
{
l[pre[i]].c -= f[e];
l[pre[i]^1].c += f[e];
}
return true;
}
int getnode(int x,int y)
{
return (x-1)*n+y;
}
int EK()
{
int cost=0,flow=0;
while(spfa(cost,flow));
return cost;
}
int main()
{
int m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int x;
scanf("%d",&x);
int sa = getnode(i,j),sb = getnode(i,j)+n*n;
build(sa,sb,x,1); build(sb,sa,-x,0);
build(sa,sb,0,m); build(sb,sa,0,0);
if(i != n)
{
int ea = getnode(i+1,j);
build(sb,ea,0,m); build(ea,sb,0,0);
}
if(j != n)
{
int ea = getnode(i,j+1);
build(sb,ea,0,m); build(ea,sb,0,0);
}
}
}
s = n*n*2+1; e = n*n*2+2;
build(s,1,0,m); build(1,s,0,0);
build(n*n*2,e,0,m); build(e,n*n*2,0,0);
n = n*n*2+2;
printf("%lld",EK());
return 0;
}
dinic:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
const int SZ=1000010;
const int INF=1000000000;
int head[SZ],nxt[SZ],tot=1,n,m;
struct edge{
int t,c;
LL d;
}l[SZ];
void build(int f,int t,LL d,int c)
{
l[++tot].t=t;
l[tot].d=d;
l[tot].c=c;
nxt[tot]=head[f];
head[f]=tot;
}
queue<int> q;
bool use[SZ];
int dist[SZ],s,e;
bool spfa()
{
for(int i = 1;i <= n;i ++) dist[i] = -INF;
dist[s] = 0;
use[s] = 1;
q.push(s);
while(q.size())
{
int f=q.front(); q.pop();
use[f] = 0;
for(int i = head[f];i;i = nxt[i])
{
int v = l[i].t;
if(l[i].c && dist[v] < dist[f] + l[i].d)
{
dist[v] = dist[f] + l[i].d;
if(!use[v])
{
use[v] = 1;
q.push(v);
}
}
}
}
if(dist[e] == -INF) return false;
return true;
}
bool vis[SZ];
int dfs(int u,int flow,LL &cost)
{
if(u == e || flow == 0) return flow;
int ans = 0;
for(int i = head[u];i;i = nxt[i])
if(!vis[i])
{
int v = l[i].t;
if(l[i].c && dist[v] == dist[u] + l[i].d)
{
vis[i] = 1;
int f = dfs(v,min(flow - ans,l[i].c),cost);
if(f > 0)
{
cost += l[i].d * l[i].c;
l[i].c -= f;
l[i^1].c += f;
ans += f;
if(flow == ans) break;
}
vis[i] = 0;
}
}
if(ans == 0) dist[u] = INF;
return ans;
}
LL dinic()
{
LL cost = 0;
while(spfa())
{
int tmp = dfs(s,INF,cost);
if(tmp == 0) break;
memset(vis,0,sizeof(vis));
}
return cost;
}
int getnode(int x,int y)
{
return (x-1)*n+y;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int x;
scanf("%d",&x);
int sa = getnode(i,j),sb = getnode(i,j)+n*n;
build(sa,sb,x,1); build(sb,sa,-x,0);
build(sa,sb,0,m); build(sb,sa,0,0);
if(i != n)
{
int ea = getnode(i+1,j);
build(sb,ea,0,m); build(ea,sb,0,0);
}
if(j != n)
{
int ea = getnode(i,j+1);
build(sb,ea,0,m); build(ea,sb,0,0);
}
}
}
s = n*n*2+1; e = n*n*2+2;
build(s,1,0,m); build(1,s,0,0);
build(n*n*2,e,0,m); build(e,n*n*2,0,0);
n = n*n*2+2;
printf("%lld",dinic());
return 0;
}