首页 > 代码库 > HDU 2686 Matrix(最大费用最大流+拆点)

HDU 2686 Matrix(最大费用最大流+拆点)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686

和POJ3422一样

删掉K把汇点与源点的容量改为2(因为有两个方向的选择)即可

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
const int maxn = 20000;
const int maxm = 800000;
const int inf = 1e8;
const int INF = 0x3f3f3f3f;
#define MIN INT_MIN
#define MAX 1e6
#define LL long long
#define init(a) memset(a,0,sizeof(a))
#define FOR(i,a,b) for(int i = a;i<b;i++)
#define max(a,b) (a>b)?(a):(b)
#define min(a,b) (a>b)?(b):(a)
using namespace std;
struct node
{
    int u,v,w,cap,next;
} edge[maxm];
int pre[maxn],dis[maxn],head[maxn],cnt;
bool vis[maxn];
int n;
void add(int u,int v,int c,int cap)
{
    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].w=c;
    edge[cnt].cap=cap;
    edge[cnt].next=head[u];
    head[u]=cnt++;

    edge[cnt].u=v;
    edge[cnt].v=u;
    edge[cnt].w=-c;
    edge[cnt].cap=0;
    edge[cnt].next=head[v];
    head[v]=cnt++;
}
int spfa(int s,int t)
{
    queue<int>q;
    while(q.empty()==false) q.pop();
    q.push(s);
    memset(vis,0,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    FOR(i,s,t+1)
    dis[i] = -1;//求最长路dis数组初始化为-1

    dis[s]=0;
    vis[s] = 1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u] = 0;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            if(edge[i].cap && dis[edge[i].v] < (dis[u]+edge[i].w))//求最长路
            {
                dis[edge[i].v] = dis[u]+edge[i].w;
                pre[edge[i].v] = i;
                if(!vis[edge[i].v])
                {
                    vis[edge[i].v]=1;
                    q.push(edge[i].v);
                }
            }
        }

    }
    if(dis[t] != -1)//------------------忘改了。。
        return 1;
    else
        return 0;
}
int MinCostMaxFlow(int s,int t)
{
    int flow=0,cost=0;
    while(spfa(s,t))
    {
        int df = inf;
        for(int i = pre[t]; i!=-1; i=pre[edge[i].u])
        {
            if(edge[i].cap<df)
                df = edge[i].cap;
        }
        flow += df;
        for(int i=pre[t]; i!=-1; i=pre[edge[i].u])
        {
            edge[i].cap -= df;
            edge[i^1].cap += df;
        }
        //printf("df = %d\n",df);
        cost += dis[t] * df;
    }
    return cost;
}
void initt()
{
    cnt=0;
    memset(head,-1,sizeof(head));
}

int ma;
int main()
{
    int s,t,k;
    while(~scanf("%d",&n))
    {
        initt();
        s = 0;
        t=2*n*n+1;
        add(s,1,0,2);
        int num = n*n;
        FOR(i,1,n+1)
        {
            FOR(j,1,n+1)
            {
                scanf("%d",&ma);
                add((i-1)*n+j,(i-1)*n+j+num,ma,1);
                add((i-1)*n+j,(i-1)*n+j+num,0,1);//本点与拆点连线,费用0,容量为无穷

                if(i<=n-1)//向下建图
                {
                    add((i-1)*n+j+num,i*n+j,0,1);
                }
                if(j<=n-1)//向右建图
                {
                     add((i-1)*n+j+num,(i-1)*n+j+1,0,1);
                }
            }
        }
        add(t-1,t,0,2);

        int ans =  MinCostMaxFlow(s,t);
        printf("%d\n",ans);
    }
    return 0;
}