UVA-10806 Dijkstra, Dijkstra. (最小费用流,网络流建模)

题目大意:给一张带权简单图,找出一条经过起点s和终点t的最小回路。

题目分析:建立网络,以s为源点,t为汇点,另每条边的容量为1,单位费用为边权值。求最小费用流,增广两次后的最小费用便是答案。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<cmath>
# include<string>
# include<vector>
# include<list>
# include<set>
# include<map>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

# define LL long long
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a))
# define CLL(a,b,n) fill(a,a+n,b)

const double inf=1e30;
const int INF=1<<30;
const int N=105;

struct Edge
{
    int fr,to,cap,flow,cost;
    Edge(int _fr,int _to,int _cap,int _flow,int _cost):fr(_fr),to(_to),cap(_cap),flow(_flow),cost(_cost){}
};
vector<Edge>edges;
vector<int>G[N];
int p[N],a[N],d[N],inq[N];

void init(int n)
{
    edges.clear();
    REP(i,0,n) G[i].clear();
}

void addEdge(int u,int v,int cost)
{
    edges.push_back(Edge(u,v,1,0,cost));
    edges.push_back(Edge(v,u,0,0,-cost));
    int m=edges.size();
    G[u].push_back(m-2);
    G[v].push_back(m-1);
}

bool BellmanFord(int s,int t,int &flow,int &cost)
{
    CL(inq,0);
    CLL(d,INF,t+1);
    d[s]=0,inq[s]=1,p[s]=0,a[s]=INF;

    queue<int>q;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        inq[u]=0;
        REP(i,0,G[u].size()){
            Edge &e=edges[G[u][i]];
            if(d[e.to]>d[u]+e.cost&&e.cap>e.flow){
                d[e.to]=d[u]+e.cost;
                p[e.to]=G[u][i];
                a[e.to]=min(a[u],e.cap-e.flow);
                if(!inq[e.to]){
                    inq[e.to]=1;
                    q.push(e.to);
                }
            }
        }
    }
    if(d[t]==INF) return false;
    flow+=a[t];
    cost+=a[t]*d[t];
    for(int x=t;x!=s;x=edges[p[x]].fr){
        edges[p[x]].flow+=a[t];
        edges[p[x]^1].flow-=a[t];
    }
    return true;
}

void solve(int s,int t)
{
    int flow=0,cost=0;
    if(!BellmanFord(s,t,flow,cost)) printf("Back to jail\n");
    else{
        if(BellmanFord(s,t,flow,cost)) printf("%d\n",cost);
        else printf("Back to jail\n");
    }
}

int main()
{
    int s,t,n,m,a,b,c;
    while(scanf("%d",&n)&&n)
    {
        s=0,t=n-1;
        init(n);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            addEdge(a-1,b-1,c);
            addEdge(b-1,a-1,c);
        }
        solve(s,t);
    }
    return 0;
}

  

posted @ 2015-12-15 17:14  20143605  阅读(411)  评论(0编辑  收藏  举报