Dijkstra 求最短路 最大流

原来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: 30000K
Total 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

1
3 3
1 2 3
1 3 4
2 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;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra算法是单源最短路径的经典算法,其基本思想是通过逐步扩展生成最短路径集合,最终得到源点到所有其它点的最短路径。 以下是C++实现: ```c++ #include <iostream> #include <vector> #include <queue> #include <cstring> using namespace std; const int INF = 0x3f3f3f3f; // 定义正无穷 struct Edge { int to, w; Edge(int to, int w) : to(to), w(w) {} }; vector<Edge> G[100010]; // 邻接表存图 int dist[100010]; // 存储最短路径长度 bool vis[100010]; // 标记是否已经确定最短路径 void dijkstra(int s) { memset(dist, INF, sizeof(dist)); // 初始化距离为正无穷 memset(vis, false, sizeof(vis)); // 初始化标记为未确定最短路径 dist[s] = 0; // 源点到自己的距离为0 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; // 小根堆 q.push(make_pair(0, s)); // 将源点入队 while(!q.empty()) { int u = q.top().second; // 取出当前距离最小的点 q.pop(); if(vis[u]) continue; // 如果已经确定最短路径,直接跳过 vis[u] = true; // 标记为已确定最短路径 for(auto e : G[u]) { // 遍历所有相邻的点 int v = e.to; int w = e.w; if(dist[v] > dist[u] + w) { // 如果当前路径更优 dist[v] = dist[u] + w; // 更新最短路径距离 q.push(make_pair(dist[v], v)); // 将该点加入小根堆 } } } } int main() { int n, m, s; cin >> n >> m >> s; for(int i = 0; i < m; i++) { int u, v, w; cin >> u >> v >> w; G[u].push_back(Edge(v, w)); } dijkstra(s); for(int i = 1; i <= n; i++) { if(dist[i] == INF) cout << "INF" << endl; // 如果不连通,输出INF else cout << dist[i] << endl; } return 0; } ``` 输入格式:第一行输入三个整数n,m,s,表示图的点数、边数和源点编号。接下来m行每行三个整数u,v,w,表示一条从u到v的有向边,边权为w。 输出格式:输出n行,每行一个整数,表示源点到每个点的最短路径长度。若不连通,则输出INF。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值