Dijkstra 求最短路 最大流

来源:互联网 发布:淘宝店怎么才能有人气 编辑:程序博客网 时间:2024/06/06 01:37
原来Dijkstra算法不光只能求最短路问题,还能求最大流问题~~~Dijkstra <wbr>求最短路 <wbr>最大流
最短路问题时,Dijkstra算法的基本思想:
 
邻接矩阵w[x][y]保存x和y间的距离(别的设为INF,表示不连通,设为-1也行,后来更新加一个if(w[x][y]>=0)),数组d保存通过已经确定的点从起点到每个点的最短路。初始化d[0]=0,别的都是INF。循环n次,每次确定一个点,最后的d[n]就是答案。
 怎么每次确定一个点呢?就是在所有还未确定的点中找到d最小的点。因为如果d[x]是剩下的里面最小的,x这个点的最短路已经被确定(假设通过别的点再到x,起点到别的点路径本来就比到x长,再加上那个点到x的距离就更长了。。)找到x之后把x标记为访问,然后对于所有从x出发的边(x,y),更新d[y]=min(d[y],d[x]+w[x][y])。
Dijkstra算法只能用于边权均为正的情况。复杂度O(N^2)

具体代码:

memset(vis,0,sizeof(vis));
int i;
for(i=0; i<n; i++) d[i]=(i==0?0:INF);
for(i=0; i<n; i++)
{
    int x,y,m=INF;
    for(y=0; y<n; y++) if(!vis[y]&&d[y]<=m) m=d[x=y];
    vis[x]=1;
    for(y=0; y<n; y++) d[y]=d[y]<d[x]+w[x][y]?d[y]:d[x]+w[x][y];
}



若要打印节点,只要把d[y]=d[y]<d[x]+w[x][y]?d[y]:d[x]+w[x][y]改成
if(d[y]>d[x]+w[x][y])
{
   d[y]=d[x]+w[x][y];
   fa[y]=x;
}

但是又怎么用Dijkstra求最大流呢?其实也是每次确定一个点,更新此时每个点能通过的最大流。初始化d[0]=INF(一开始有无穷大的流),别的都是-1(代表没有)。不连通的w[x][y]也设为-1。每次循环找到d最大的点(能允许的流最大),更新的时候注意是d[y]=d[y]>min(d[x],w[x][y])?d[y]:min(d[x],w[x][y])。
总之就是把原来的最小都换成现在的最大。。

POJ 1797
Heavy Transportation
Time Limit: 3000MS Memory Limit: 30000KTotal Submissions: 17277 Accepted: 4536

Description

Background
Hugo Heavy is happy. After the breakdown of the Cargolifter projecthe can now expand business. But he needs a clever man who tells himwhether there really is a way from the place his customer has buildhis giant steel crane to the place where it is needed on which allstreets can carry the weight.
Fortunately he already has a plan of the city with all streets andbridges and all the allowed weights.Unfortunately he has no ideahow to find the the maximum weight capacity in order to tell hiscustomer how heavy the crane may become. But you surely know.

Problem
You are given the plan of the city, described by the streets (withweight limits) between the crossings, which are numbered from 1 ton. Your task is to find the maximum weight that can be transportedfrom crossing 1 (Hugo's place) to crossing n (the customer'splace). You may assume that there is at least one path. All streetscan be travelled in both directions.

Input

The first line contains the number of scenarios(city plans). For each city the number n of street crossings (1<= n <= 1000) and number m of streetsare given on the first line. The following m lines contain triplesof integers specifying start and end crossing of the street and themaximum allowed weight, which is positive and not larger than1000000. There will be at most one street between each pair ofcrossings.

Output

The output for every scenario begins with a linecontaining "Scenario #i:", where i is the number of the scenariostarting at 1. Then print a single line containing the maximumallowed weight that Hugo can transport to the customer. Terminatethe output for the scenario with a blank line.

Sample Input

13 31 2 31 3 42 3 5

Sample Output

Scenario #1:4代码:
#include<stdio.h>#include<math.h>#include<string.h>int map[1010][1010],d[1010],vis[1010],n,m;int min(int a,int b){    return a<b?a:b;}void dijkstra(){    memset(vis,0,sizeof(vis));    int i;    for(i=1; i<=n; i++) d[i]=(i==1?1000000:-1);    for(i=1; i<=n; i++)    {        int x,m=-1,y;        for(y=1; y<=n; y++) if(!vis[y]&&d[y]>m) m=d[x=y];        vis[x]=1;        for(y=1; y<=n; y++) if(map[x][y]>=0&&!vis[y])d[y]=d[y]>min(d[x],map[x][y])?d[y]:min(d[x],map[x][y]);    }}int main(){    int N,T;    scanf("%d",&N);    for(T=1; T<=N; T++)    {        int a,b,c;        memset(map,-1,sizeof(map));        memset(vis,0,sizeof(vis));        scanf("%d%d",&n,&m);        while(m--)        {            scanf("%d%d%d",&a,&b,&c);            map[a][b]=map[b][a]=c;        }        dijkstra();        printf("Scenario #%d:\n",T);        printf("%d\n",d[n]);        if(T<N) puts("");    }    return 0;}