Matrix Again HDU 3376 最大费用最大流

来源:互联网 发布:kf5雾化器做芯数据 编辑:程序博客网 时间:2024/05/20 18:41

题目大意

给你一个N*N的矩阵,每个元素代表该处的权值。要求每个点只能走一次,左上角和右下角可以走两次但该处的权值只能获取一次。问你从左上角走到右下角(只能向下或右移动),再从右下角回到左上角(只能向上或左移动)所能得到的最大权值。

分析

我们可以转化为从【左上角起点】到【右下角终点】走两次所获的最大权值。然后和poj3422 一样了。

ps:要人品的,我超时了10多次,然后就在不经意间A了两次!!!

code

#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<string>#include<queue>;using namespace std;struct arr{    int x,y,w,c,next;}edge[5000000];int ls[750000];int dis[750000];int f[5000000];int v[750000];int sign[750000]; int edge_m;int ans;int s,t;int n,m;int add(int x,int y,int w,int c){    edge_m++;    edge[edge_m]=(arr){x,y,w,c,ls[x]},f[edge_m]=w,ls[x]=edge_m;     edge_m++;    edge[edge_m]=(arr){y,x,w,-c,ls[y]},f[edge_m]=0,ls[y]=edge_m;} int lon;bool bfs(){    memset(dis,-31,sizeof(dis));    memset(v,0,sizeof(v));    int inf=dis[s];    dis[s]=0;    v[s]=0;    queue<int> q;    q.push(s);    do    {        int x=q.front();        q.pop();        for (int i=ls[x];i;i=edge[i].next)        {            if ((dis[edge[i].y]<dis[x]+edge[i].c)&&(f[i]))            {                dis[edge[i].y]=dis[x]+edge[i].c;                sign[edge[i].y]=i;                if (!v[edge[i].y])                {                    v[edge[i].y]=1;                    q.push(edge[i].y);                }            }            lon=lon+1000;        }        v[x]=0;    }while (!q.empty());    if (dis[t]!=inf)    return true;    else    return false;}void mcf(){    int mn=2000000000;    int x=t;    while (sign[x])    {        mn=min(mn,f[sign[x]]);        x=edge[sign[x]].x;    }    ans+=mn*dis[t];    x=t;    while (sign[x])    {        f[sign[x]]-=mn;        f[sign[x]^1]+=mn;        x=edge[sign[x]].x;    }}int dinic(){    while (bfs())    {        mcf();    }}int a[900][900];int main(){    while (scanf("%d",&n) != EOF){    m=2;    edge_m=1;    memset(ls,0,sizeof(ls));    s=0; t=n*n*2+1;    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            scanf("%d",&a[i][j]);    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            add(n*n+(i-1)*n+j,(i-1)*n+j,1,a[i][j]);    add(n*n+1,1,m-1,0);    add(n*n*2,n*n,m-1,0);    for (int i=2;i<=n;i++)        for (int j=2;j<=n;j++)        {            add((i-2)*n+j,n*n+(i-1)*n+j,m,0);            add((i-1)*n+j-1,n*n+(i-1)*n+j,m,0);        }    for (int i=2;i<=n;i++)        add(i-1,n*n+i,m,0);    for (int i=2;i<=n;i++)        add((i-2)*n+1,n*n+(i-1)*n+1,m,0);    add(0,n*n+1,m,0);    add(n*n,t,m,0);    ans=0;    dinic();    printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击