poj2135 最小费用最大流模板

点击打开链接
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>

using namespace std;
#define V 10010
#define E 100010
#define inf 0x3f3f3f3f

struct Edge{
    int x,y,next,cap,cost;
}edge[E];

int pre[V],dist[V],head[V],vis[V];
int cnt = 0;

void init()
{
    cnt = 0;
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int c,int cost)
{
    edge[cnt].x=u;edge[cnt].y=v;edge[cnt].cost=cost;
    edge[cnt].cap=c;edge[cnt].next=head[u];head[u]=cnt++;

    edge[cnt].x=v;edge[cnt].y=u;edge[cnt].cost=-cost;
    edge[cnt].cap=0;edge[cnt].next=head[v];head[v]=cnt++;//注意反向边cap为0!!WA好几次...
}
int spfa(int start,int end)
{
    queue<int>q;
    for(int i=0;i<=end+2;i++){
        dist[i]=inf,vis[i]=0,pre[i]=-1;
    }
    vis[start]=1,dist[start]=0;
    q.push(start);
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        int u,v;
        u=now;
        vis[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            if(edge[i].cap>0)
            {
                v=edge[i].y;
                if(dist[v]>dist[u]+edge[i].cost)
                {
                    dist[v]=dist[u]+edge[i].cost;
                    pre[v]=i;//记录前驱
                    if(!vis[v])
                    {
                        q.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
    }
    return dist[end]!=inf;
}

int MCMF(int begin,int end)
{
    int ans=0,flow,flow_sum=0;
    while(spfa(begin,end))
    {
        flow=inf;
        for(int i=pre[end];i!=-1;i=pre[edge[i].x])flow=min(flow,edge[i].cap);
        //cout<<flow<<endl;
        for(int i=pre[end];i!=-1;i=pre[edge[i].x]){
            edge[i].cap-=flow;
            edge[i^1].cap+=flow;//i^1就变成反边了?高大上...
        }
        flow_sum+=flow;
        ans+=dist[end];//这题最大流只有1或0,一般化的是flow*dist[end];
    }
    return ans;
}


int main()
{
    //freopen("in.txt","r",stdin);
    int n,m,a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        addedge(0,1,2,0);
        addedge(n,n+1,2,0);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c);
            addedge(a,b,1,c);
            addedge(b,a,1,c);
        }
        printf("%d\n",MCMF(0,n+1));
    }
    return 0;
}


posted @ 2016-05-02 11:23  adfae  阅读(113)  评论(0编辑  收藏  举报