UVA 10806 Dijkstra, Dijkstra.

题意:

  从起点走到终点,然后从终点走到起点,其中不能同时走过相同的一条边,问你最小路径长度。先输入终点n,起点为1,接下来输入m,代表有m条边。每条边由起点,终点,长度组成。  

分析:

  求最小长度,还限定了每条路只能一次,所以可以用网络流来接。长度就是边费用,每条边的流量为1,这样实现了每条边只能走一次。从起点走到终点再从终点走到起点,相当于在起点前连一个外起点,流量为2,。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn=110;
const int INF=1e9;
int n,m,s,t;
int inq[maxn];
int d[maxn],p[maxn],a[maxn];
int flow,cost;
struct Edge
{
    int from,to,cap,flow,cost;
};
vector<Edge>edges;
vector<int>G[maxn];
void init()
{
    flow=cost=s=0;
    t=n;
    for(int i=0;i<t+1;i++)
        G[i].clear();
    edges.clear();
}
void add(int from,int to,int cap,int cost)
{
    edges.push_back((Edge){from,to,cap,0,cost});
    edges.push_back((Edge){to,from,0,0,-cost});
    int nc=edges.size();
    G[from].push_back(nc-2);
    G[to].push_back(nc-1);
}
bool bell(int& flow,int& cost)
{
    for(int i=0;i<=t;i++)
        d[i]=INF;
    memset(inq,0,sizeof(inq));
    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;
        for(int i=0;i<G[u].size();i++)
        {
            Edge& e=edges[G[u][i]];
            if(e.cap>e.flow&&d[e.to]>d[u]+e.cost)
            {
                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])
                {
                    q.push(e.to);
                    inq[e.to]=1;
                }
            }
        }

    }
    if(d[t]==INF)
        return false;
    flow+=a[t];
    cost+=d[t]*a[t];
    int u=t;
    while(u!=s)
    {
        //cout<<3<<endl;
        edges[p[u]].flow+=a[t];
        edges[p[u]^1].flow-=a[t];
        u=edges[p[u]].from;
    }
    return true;
}
int main()
{
    while(scanf("%d",&n),n)
    {
        scanf("%d",&m);
        init();
        int a,b,c;
        add(0,1,2,0);
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,1,c);
            add(b,a,1,c);
        }
        //cout<<1<<endl;
        while(bell(flow,cost));
        //cout<<2<<endl;
        if(flow<2)
            printf("Back to jail\n");
        else
            printf("%d\n",cost);
    }
}

输入:

2

1

1 2 999

3

3

1 3 10

2 1 20

3 2 50

9

12

1 2 10

1 3 10

1 4 10

2 5 10

3 5 10

4 5 10

5 7 10

6 7 10

7 8 10

6 9 10

7 9 10

8 9 10

0

输出:

Back to jail

80

Back to jail

posted @ 2016-08-11 16:51  幻世沉溺  阅读(230)  评论(0编辑  收藏  举报