(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算法