poj1797Heavy Transportation(dijkstra)

本文介绍了一种使用Dijkstra算法解决图中单源最短路径问题的方法,并通过优化实现更高效的计算。针对大规模数据集,文章详细解释了如何利用优先队列将复杂度降低至O(n²logn),并通过实例代码展示了具体的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题和昨天做的poj2253 Frogger(用单源最短路dijkstra的思路求解) 几乎一模一样,只是点的数量范围从200变成了1000,不优化O(n^3)肯定超时,所以要用优先队列优化到O(n^2logn)。
需要注意的一点就是两点不可达则令w=0。
如果起点和终点重合,那么输出一个不小于1000000的数即可。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000;

priority_queue<int>pq[maxn+5];

int n;
int d[maxn+5];
int w[maxn+5][maxn+5];

bool vis[maxn+5];

int find(){
    int maxi=-1;
    int maxd=0;
    for(int i=1;i<=n;i++)if(vis[i]==false){
        d[i]=max(d[i],pq[i].top());
        if(d[i]>maxd){
            maxd=d[i];
            maxi=i;
        }
    }
    return maxi;
}

void update(int cur){
    for(int i=1;i<=n;i++)if(vis[i]==false){
        pq[i].push(min(d[cur],w[cur][i]));
    }
}

void initpq(){
    for(int i=1;i<=n;i++){
        while(!pq[i].empty())pq[i].pop();
        for(int j=1;j<=n;j++){
            pq[i].push(min(d[j],w[i][j]));
        }
    }
}

void dj(int cur){
    memset(vis,false,sizeof(vis));
    memset(d,0,sizeof(d)),d[cur]=inf;
    initpq();
    while((cur=find())!=-1){
        vis[cur]=true;
        update(cur);
    }
}


int main(){
    int T;
    scanf("%d",&T);
    for(int t=1;t<=T;t++){
        int m;
        scanf("%d%d",&n,&m);
        memset(w,0,sizeof(w));
        while(m--){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            w[x][y]=w[y][x]=z;
        }
        dj(1);
        printf("Scenario #%d:\n",t);
        printf("%d\n\n",d[n]);
    }
}
POJ1797是一道经典的图论问题,主要考察的是最小生成树(MST)的应用。题目要求在一个无向图中找到一条路径,使得路径上的最大边权最小。这个问题可以通过Kruskal算法来解决。 ### 问题描述 给定一个无向图,图中有N个顶点和M条边。每条边有一个权值,要求找到一条路径,使得路径上的最大边权最小。 ### 解题思路 1. **Kruskal算法**:Kruskal算法是一种贪心算法,用于求解最小生成树。它通过不断选择最小权值的边来构建生成树,同时避免形成环。 2. **并查集(Union-Find)**:用于检测环的存在。每当加入一条边时,检查这条边连接的两个顶点是否已经在同一个连通分量中。如果在同一个连通分量中,则形成环;否则,将这两个顶点合并。 ### 代码实现 以下是使用Java实现的Kruskal算法来解决POJ1797问题的示例代码: ```java import java.util.Arrays; import java.util.Scanner; class Edge implements Comparable<Edge> { int u, v, weight; Edge(int u, int v, int weight) { this.u = u; this.v = v; this.weight = weight; } @Override public int compareTo(Edge other) { return this.weight - other.weight; } } public class Main { static int[] parent; static int find(int x) { if (parent[x] != x) { parent[x] = find(parent[x]); } return parent[x]; } static void union(int x, int y) { int xroot = find(x); int yroot = find(y); if (xroot != yroot) { parent[xroot] = yroot; } } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int T = scanner.nextInt(); for (int t = 1; t <= T; t++) { int N = scanner.nextInt(); int M = scanner.nextInt(); Edge[] edges = new Edge[M]; for (int i = 0; i < M; i++) { int u = scanner.nextInt(); int v = scanner.nextInt(); int weight = scanner.nextInt(); edges[i] = new Edge(u, v, weight); } parent = new int[N + 1]; for (int i = 1; i <= N; i++) { parent[i] = i; } Arrays.sort(edges); int maxEdge = -1; for (Edge edge : edges) { if (find(edge.u) != find(edge.v)) { maxEdge = Math.max(maxEdge, edge.weight); union(edge.u, edge.v); } } System.out.println("Scenario #" + t + ":"); System.out.println(maxEdge); if (t < T) { System.out.println(); } } scanner.close(); } } ``` ### 代码解释 1. **Edge类**:表示图中的边,并实现了Comparable接口以便排序。 2. **find方法**:查找某个顶点的根节点。 3. **union方法**:合并两个顶点所在的集合。 4. **main方法**:读取输入数据,构建边列表,排序并应用Kruskal算法,最后输出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值