您的位置:首页 > 其它

POJ 3422 Kaka's Matrix Travels(最小费用最大流+拆点)

2013-02-27 11:21 288 查看
题目链接

关键在于建图,昨天做的的时候直接想错了。放了放,在路上和gyx讨论了一下,他说是不是拆点,我一想真是啊。。。

然后想了想建图的细节。。。今天写了程序,居然把电脑给写挂了。。第一次啊,可见程序写的多不靠谱啊。。

把一个点拆成两个点,这两个点之间的流量为1,费用为权值,这条边的起点和终点都可以连接下个位置的起点。

为了控制流量,多加了k个点,这多出来的k个点,到终点的流量为1,来控制最终的流量。剩下的就是模版了,改了一下求最大。

这样建图效率不是很高,想会不会超时。。。果真TLE了,不过数组开小了,开大之后,水过400+ms。。。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define INF 0x7fffffff

int p[51][51];

int low[6001],path[6001];
int first[6001],in[6001],dis[6001];
int str,end,t;
struct node
{
int u,v,w,cost,re,next;
}edge[900001];
int ans;
void CL()
{
t = 1;
memset(first,-1,sizeof(first));
}
void add(int u,int v,int w,int cost)
{
edge[t].u = u;
edge[t].v = v;
edge[t].w = w;
edge[t].cost = cost;
edge[t].re = t+1;
edge[t].next = first[u];
first[u] = t ++;

edge[t].u = v;
edge[t].v = u;
edge[t].w = 0;
edge[t].cost = -cost;
edge[t].re = t-1;
edge[t].next = first[v];
first[v] = t ++;
}
int bfs()
{
int u,i,v;
memset(path,-1,sizeof(path));
for(i = 0;i <= end;i ++)
{
dis[i] = -INF;
in[i] = 0;
}
queue<int>que;
que.push(str);
dis[str] = 0;
in[str] = 1;
low[str] = INF;
while(!que.empty())
{
u = que.front();
in[u] = 0;
que.pop();
for(i = first[u];i != -1;i = edge[i].next)
{
v = edge[i].v;
if(edge[i].w&&dis[v] < dis[u]+edge[i].cost)
{
dis[v] = dis[u] + edge[i].cost;
path[v] = i;
low[v] = low[u] < edge[i].w ? low[u]:edge[i].w;
if(!in[v])
{
que.push(v);
in[v] = 1;
}
}
}
}
if(path[end] == -1)
return -1;
else
return low[end];

}
void mcmf()
{
int res,temp,now;
while((res = bfs()) != -1)
{
now = end;
while(now != str)
{
temp = path[now];
edge[temp].w -= res;
edge[edge[temp].re].w += res;
ans += res*edge[temp].cost;
now = edge[temp].u;
}
}
}
int main()
{
int n,i,j,k;
int x,y;
ans = 0;
CL();
scanf("%d %d",&n,&k);
for(i = 1;i <= n;i ++)
{
for(j = 1;j <= n;j ++)
scanf("%d",&p[i][j]);
}
str = 0;
end = 2*n*n + k + 1;
add(str,1,INF,0);
for(i = 1;i <= n;i ++)
{
for(j = 1;j <= n;j ++)
{
x = (i-1)*n + j;
y = x + n*n;
add(x,y,1,p[i][j]);
if(i + 1 <= n)
{
add(x,x+n,INF,0);
add(y,x+n,INF,0);
}
if(j + 1 <= n)
{
add(x,x+1,INF,0);
add(y,x+1,INF,0);
}
}
}
for(i = 1;i <= k;i ++)
{
add(x,2*n*n+i,INF,0);
add(y,2*n*n+i,INF,0);
add(2*n*n+i,end,1,0);
}
mcmf();
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: