无向图最小费用最大流+uva10594

来源:互联网 发布:java二叉树前序遍历 编辑:程序博客网 时间:2024/05/22 05:29

思路:无向图,加边时需要两个方向,然后加一个超级源点0,0到1的容量为D,然后求最小费用最大流,如果=D,则输出最小费用,否则Impossible.注意数据的范围,要用long long。

附代码:

#include<iostream>#include<cstdio>#include<queue>#include<cstring>using namespace std;typedef long long LL;const LL INF=10000000000000000;const int maxn=110;const int maxm=5050;struct node{    int u,v,next,cap;    LL cost;}edge[maxm*4];int vis[maxn],pre[maxn],head[maxn];LL dis[maxn];int N,M,num;LL D,K;void add_edge(int x,int y,LL f){    edge[num].u=x;    edge[num].v=y;    edge[num].cost=f;    edge[num].next=head[x];    head[x]=num++;    edge[num].u=y;    edge[num].v=x;    edge[num].cost=-f;    edge[num].next=head[y];    head[y]=num++;}bool spfa(int s,int t){    int cur;    for(int i=0;i<=N;i++)    {        dis[i]=INF;        vis[i]=0;        pre[i]=-1;    }    queue<int> q;    q.push(s);    dis[s]=0;    vis[s]=1;    while(!q.empty())    {        cur=q.front();        q.pop();        vis[cur]=0;        for(int i=head[cur];i!=-1;i=edge[i].next)        {            if(edge[i].cap)            {                int v=edge[i].v;                if(dis[v]>dis[cur]+edge[i].cost)                {                    dis[v]=dis[cur]+edge[i].cost;                    pre[v]=i;                    if(!vis[v])                    {                        vis[v]=1;                        q.push(v);                    }                }            }        }    }    return dis[t]!=INF;}LL mincost(int s,int t){    LL flow=INF,ans1=0,ans=0;    while(spfa(s,t))    {        for(int i=pre[t];i!=-1;i=pre[edge[i].u])        flow=flow>edge[i].cap?edge[i].cap:flow;        ans1+=flow;        ans+=flow*dis[t];        for(int i=pre[t];i!=-1;i=pre[edge[i].u])        {            edge[i].cap-=flow;            edge[i^1].cap+=flow;        }    }    return ans1==D?ans:-1;}int main(){    #ifndef ONLINE_JUDGE        freopen("in.txt","r",stdin);    #endif    int x,y;    LL f;    while(scanf("%d%d",&N,&M)!=EOF)    {        num=0;        memset(head,-1,sizeof(head));        for(int i=0;i<M;i++)        {            scanf("%d%d%lld",&x,&y,&f);            add_edge(x,y,f);            add_edge(y,x,f);        }        scanf("%lld%lld",&D,&K);        add_edge(0,1,0);        edge[num-2].cap=D;        edge[num-1].cap=0;        for(int i=0;i<num-2;i++)        {            if(edge[i].cost<0)edge[i].cap=0;            else edge[i].cap=K;        }        LL ans=mincost(0,N);        if(ans==-1)cout<<"Impossible."<<endl;        else cout<<ans<<endl;    }    return 0;}


0 0
原创粉丝点击