考研机试第六天

本文探讨了两种经典图论算法在解决实际问题中的应用。Dijkstra算法用于寻找图中两点间的最短路径,适用于非负权重图。而另一算法则通过构造最小生成树解决平面点集间连接的最小线段长度和问题,采用Prim或Kruskal策略。这两个算法在路径规划和网络优化中有广泛应用。
摘要由CSDN通过智能技术生成

(5)最短路径
问题11:某省自从实行了很多年的畅通工程后,修建了很多路,不过路多也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离短很多,这让行人很困扰

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#include<climits>
using namespace std;

const int MAXN = 200;
const int INF = INT_MAX;//无穷,0x7fffffff也可以

struct Edge{
     int to;//连接的顶点
     int length;//路径长度
     Edge(int n,int l):to(t),length(l){}
};

struct Point{//优先队列,选择离源点最近的点
     int number;
     int distance;
     Point(int n,int d):number(n),distance(d){}
     bool operator < (const Point &p){
          return distance > p.distance;
     }
};
     
vector<int> graph[MAXN];//由向量数组存储邻接表
int dis[MAXN];//距离向量
bool visit[MAXN];//标记,为true时表示最短路径长度已达到

void Dijkstra(int start,int n){
     //memset(visit,false,sizeof(visit));
     fill(dis,dis + n,INF);
     dis[start] = 0;
     priority_queue<Point>myPriorityQueue;
     myPriorityQueue.push(Point(start,dis[start]))
     for(int i = 0; i < n; ++i){
        int u = -1;
        for(int j = 0;j < n; ++j){
           if(visit[j]) continue;
           if(u = -1 || dis[j] < dis[u]){
              u = j;
           }
         }
         for(int j = 0;j < graph[u].size;++j){
            int v = graph[u][j].to;
            int d = graph[u][j].length;
            if(dis[u] + d < dis[v]){
               dis[v] = dis[u] + d;
            }
         }
         visit[u] = true;
      }
      return;
 }
 int main(){
     int n,m;
     while(scanf("%d%d",&n.&m) != EOF){
          memset(graph,0,sizeof(graph));
          while(m--){
              int from,to,length;
              scanf("%d%d%d",&from,&to,&length);
              graph[from].push_back(Edge(form,length));
              graph[to].push_back(Edge(to,length));
              }
              int start;
              int terminal;
              scanf("%d%d",start,&terminal);
              Dijkstra(start,n);
              if(dis[terminal] == INF){
                 dis[terminal] = -1;
              }
       }
 }

问题12:平面上有若干个点,需要一些线段来将这些点连接起来使任意两点能够通过一系列的线段相连,给出所有点的坐标,求一种连接方式使所有线段的长度和最小,并求长度和。

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define N 101;
int Tree[N];
int FindRoot(int x){//查找结点x所在树的根结点
    if(Tree[x] == -1) return x;
    else{
        int tmp = findRoot(Tree(x));
        Tree[x] = tmp;
        return tmp;
    }
}
struct Edge{
     int a,b;
     double cost;//权值变为长度,故改用浮点数
     bool operator < (conxt Edge &A) const{
          return cost < A.cost;
     }
}edge[6000];
struct Point{//点结构体
     double x,y;
     double getDistance(Point A){//计算两点之间的距离
          double tmp = (x-A.x)*(x-A.x)+(y-A.y)*(y-A.y);
          return sqrt(tmp);
     }
}list[101];
int main(){
    int n;
    while(scanf("%d",&n) != EOF){
         for(int i = 1;i <= n;i++){
             scanf("%lf%lf",&list[i].x,&list[i].y);
         }
         int size = 0;//抽象出边的总数
         for(int i = 1;i <= n;i++){
            for(j = i+1;j <= n;j++){//连接两条线段抽象成边
               edge[size].a = i;
               edge[size].b = j;//该边的两个顶点编号
               edge[size].cost = list[i].getDistance(list[j]);//边权值为两点之间长度
               size++;
            }//遍历所有顶点对
         }
         sort(edge,edge+size);//边权值按递增排序
         for(int i = 1;i<=n;i++){
            Tree[i] = -1;
         }
         double ans = 0;
         for(int i = 0;i < size;i++){
            int a = findRoot[edge[i].a];
            int b = findRoot[edge[i].b];
            if(a != b){
              Tree[a] = b;
              ans += edge[i].cost;
            }
         }//最小生成树
         printf("%.2lf\n",ans);
      }
      return 0;
 }

最后总结一下,Dijstra算法在负权图上不成立,若要求解负权图上的最短路径,则要使用SPFA算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值