上一题的模板应用,好久没做图论,结果建图一塌糊涂。。。
题意,给出一个矩阵,求从左上角到右下角走k次使路上所得的权值最大,其中经过一个权值后,该点权值清零。
思路:建图,每一个格子为一个点,同时衍生另外一个点,用来存清零后的路线,则每个点有两条路,一条是容量为1,权值为给出的值,一条为容量为k,权值为0;
因为求得是最大,所以建图的时候用1000减去原来的数,求出的最小费再用k*2(n-1)*1000减去,所得的值就为最大值了。
算是理解一下别人的模板吧,建图用时间比较长,最后建完图后,发现TLE了,结果去把范围给开大后,AC了,难道范围小了不应该RE么。。。囧
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define typef int
#define typec int
#define maxn 6000
#define maxm 30005
#define N maxn + 2
#define E maxm * 4 + 4
const typef inff = 0x3f3f3f3f;
const typec infc = 0x3f3f3f3f;
int map[55][55];
struct network
{
int nv, ne, pnt[E], nxt[E];
int vis[N], que[N], head[N], pv[N], pe[N];
typef flow, cap[E];
typec cost, dis[E], d[N];
void addedge(int u, int v, typef c, typec w)
{
pnt[ne] = v;
cap[ne] = c;
dis[ne] = +w;
nxt[ne] = head[u];
head[u] = (ne++);
pnt[ne] = u;
cap[ne] = 0;
dis[ne] = -w;
nxt[ne] = head[v];
head[v] = (ne++);
}
int mincost(int src, int sink)
{
int i, k, f, r;
typef mxf;
for (flow = 0, cost = 0;;)
{
memset(pv, -1, sizeof(pv));
memset(vis, 0, sizeof(vis));
for (i = 0; i < nv; ++i)
d[i] = infc;
d[src] = 0;
pv[src] = src;
vis[src] = 1;
for (f = 0, r = 1, que[0] = src; r != f;)
{
i = que[f++];
vis[i] = 0;
if (N == f)
f = 0;
for (k = head[i]; k != -1; k = nxt[k])
if (cap[k] && dis[k] + d[i] < d[pnt[k]])
{
d[pnt[k]] = dis[k] + d[i];
if (0 == vis[pnt[k]])
{
vis[pnt[k]] = 1;
que[r++] = pnt[k];
if (N == r)
r = 0;
}
pv[pnt[k]] = i;
pe[pnt[k]] = k;
}
}
if (-1 == pv[sink])
break;
for (k = sink, mxf = inff; k != src; k = pv[k])
if (cap[pe[k]] < mxf)
mxf = cap[pe[k]];
flow += mxf;
cost += d[sink] * mxf;
for (k = sink; k != src; k = pv[k])
{
cap[pe[k]] -= mxf;
cap[pe[k] ^ 1] += mxf;
}
}
return cost-1000+map[1][1];
}
void build(int v,int n,int k)
{
nv = v;
ne = 0;
memset(head, -1, sizeof(head));
int x, y;
typec w;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
map[i][j]=1000-map[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i-1>=1&&j-1<=0)
{
addedge(n*(i-2)+j, n*(i-1)+j, 1, map[i][j]);
addedge(n*(i-2)+j,n*(i-1)+j+n*n,k,1000);
addedge(n*(i-1)+j+n*n, n*(i-1)+j, k, 0);
}
else if(j-1>=1&&i-1<=0)
{
addedge(n*(i-1)+j-1,n*(i-1)+j, 1, map[i][j]);
addedge(n*(i-1)+j-1,n*(i-1)+j+n*n,k,1000);
addedge(n*(i-1)+j+n*n, n*(i-1)+j, k, 0);
} //2*n+n*n
else if(j-1>=1&&i-1>=1)
{
addedge(n*(i-1)+j-1,n*(i-1)+j+n*n,k,0);
addedge(n*(i-2)+j, n*(i-1)+j+n*n,k,0);
addedge(n*(i-2)+j, n*(i-1)+j, k, 1000);
addedge(n*(i-1)+j-1,n*(i-1)+j, k, 1000);
addedge(n*(i-1)+j+n*n,n*(i-1)+j, 1, map[i][j]);
}
}
addedge(0, 1, k, 1000); //答案加上map【1】【1】;
addedge(n*n, 2*n*n+1, k, 0);
}
} g;
int n, m,k;
int main()
{
//freopen("t.txt", "r", stdin);
scanf("%d%d", &n, &k);
g.build(2*n*n + 2,n,k);
if(k==0)
printf("0\n");
else
printf("%d\n",k*(2*n-1)*1000-g.mincost(0, 2*n*n + 1));
return 0;
}