UVA 10806 Dijkstra, Dijkstra.

时间:2023-03-09 00:23:53
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