poj 1797 dij变形

本文介绍了一个使用Dijkstra算法解决图中单源最短路径问题的C++程序实例。该程序通过读取输入文件来构建图,并利用Dijkstra算法计算从指定起点到图中所有其他节点的最短距离。
  1. #include<iostream>
  2. usingnamespacestd;
  3. inttable[1001][1001]={0};
  4. intd[1001];
  5. voiddij(intN);
  6. intmain()
  7. {
  8. freopen("in.txt","r",stdin);
  9. intT,N,M,i,a,b,c,t(1);
  10. cin>>T;
  11. while(T--)
  12. {
  13. scanf("%d%d",&N,&M);
  14. for(i=0;i<M;i++)
  15. {
  16. scanf("%d%d%d",&a,&b,&c);
  17. table[a-1][b-1]=c;
  18. table[b-1][a-1]=c;
  19. }
  20. dij(N);
  21. printf("Scenario#%d:\n",t++);
  22. printf("%d\n\n",d[N-1]);
  23. memset(table,0,sizeof(table));
  24. memset(d,0,sizeof(d));
  25. }
  26. return0;
  27. }
  28. voiddij(intN)
  29. {
  30. intv(0),max(0),i,j,w;
  31. shortf[1001]={0};
  32. for(i=0;i<N;i++)
  33. d[i]=table[v][i];
  34. f[v]=1;
  35. d[v]=0;
  36. for(i=1;i<N;i++)
  37. {
  38. max=0;
  39. for(j=1;j<N;j++)
  40. if(!f[j]&&d[j]>max)
  41. {max=d[j];v=j;}
  42. f[v]=1;
  43. for(w=1;w<N;w++)
  44. if(!f[w])
  45. {
  46. if(table[v][w]>max)
  47. d[w]=max;
  48. if(table[v][w]<=max)
  49. if(table[v][w]>d[w])
  50. d[w]=table[v][w];
  51. }
  52. }
  53. }
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、付费专栏及课程。

余额充值