无权图的单源最短路:
void Unweighted( Vertex s){
queue<Vertex> q;
q.push(s);
wile(!q.empty()){
v = q.front(); q.pop();
for( V 的每个临界点 W){
dist[W] = dist[v] + 1; // 当前距离上一距离 + 1
path[W] = v; // s 到 w 的必经顶点就是前一个顶点 v
q.push(W);
}
}
}
有权图的单源最短路
void Dijkstra( Vertex s ){
while(1){
V = 未收录顶点中dist最小值;
if( 这样的V不存在 )
break;
collected[V] = true;
for( V 的每个邻接点 W )
if( collected[W] == false )
if(dist[V] + E<V,W> < dist[W]){
dist[W] = dist[V] + E<V,W>;
path[W] = V;
}
}
}
列子:
#include<bits/stdc++.h>
using namespace std;
int dist[1000]={0};//从原点到当前节点的最短路
int path[1000]={0};//当前节点的前一个节点
int G[1000][1000]={0};//图
int vis[1000]={0};
int m,n;
/*
7
12
1 2 2
1 4 1
2 4 3
2 5 10
3 1 4
3 6 5
4 3 2
4 6 8
4 7 4
4 5 2
5 7 6
7 6 1
*/
void build(){
int v1,v2;
int w;
cin>>n;
// 初始化图
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
G[i][j] = 0;
// 初始化路径
for(int i=1;i<=n;i++)
path[i] = -1;
// 初始化距离
for(int i=0;i<=n;i++)
dist[i] = 100000;
// 初始化收录情况
for(int i=1;i<=n;i++)
vis[i] = 0;
cin>>m;
// 初始化点
for(int i=0;i<m;i++){
cin>>v1>>v2>>w;
G[v1][v2] = w; // 有向图
}
}
void init(int i){
dist[i]=0;
vis[i]=1;
for(int j=1;j<=n;j++){
if(G[i][j]){
dist[j]=G[i][j];
path[j]=i;
}
}
}
int findMin(int v){
int mini=0;
for(int i=1;i<=n;i++){
if(i!=v&&!vis[i]&&dist[i]<dist[mini])mini=i;
}
return mini;
}
void Dijkstra(int v){
init(v);
while(true){
int mini=findMin(v);//第一次找出来的就是v
if(!mini)break;
vis[mini]=1;
for(int i=1;i<=n;i++){
if(!vis[i]&&G[mini][i]&&G[mini][i]+dist[mini]<dist[i]){
dist[i]=G[mini][i]+dist[mini];
path[i]=mini;
}
}
}
}
void output(){
for(int i=1;i<=n;i++)
cout<<dist[i]<<" ";
cout<<endl;
for(int i=1;i<=n;i++)
cout<<path[i]<<" ";
cout<<endl;
}
int main(){
build();
Dijkstra(1);
output();
}
多源最短路径Floyd算法
核心就是贪心,如果i,j之间不能直接相通,dist[i][j]就化成无穷大,再慢慢的取减小
void Floyd(){
for( i = 0; i < N; i++ )
for( j = 0; j < N; j++ ){
D[i][j] = G[i][j];
path[i][j] = -1;
}
for( k = 0; k < N; k++ )
for( i = 0; i< N; i++)
for( j = 0; j < N; j++ )
if( D[i][k] + D[k][j] < D[i][j] ) {
D[i][j] = D[i][k] + D[k][j];
path[i][j] = k;
}
}
列子:
#include<bits/stdc++.h>
using namespace std;
int dist[1000][1000]={0};
int G[1000][1000]={0};
int path[1000][1000]={0};
int n,m;
void init(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
G[i][j]=100000;
}
}
cin>>m;
for(int i=1;i<=m;i++){
int v1,v2,w;
cin>>v1>>v2>>w;
G[v1][v2]=w;
G[v2][v1]=w;
}
}
void floyd(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dist[i][j]=G[i][j];
path[i][j]=-1;
}
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(dist[i][k]+dist[k][j]<dist[i][j]){
dist[i][j]=dist[i][k]+dist[k][j];
path[i][j]=k;
}
}
}
}
}
void output(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<dist[i][j]<<" ";
}
cout<<endl;
}
}
int main(){
init();
floyd();
output();
}
习题1 哈利波特的考试
6 11
3 4 70
1 2 1
5 4 50
2 6 50
5 6 60
1 3 70
4 6 60
3 6 80
5 1 100
2 4 60
5 2 80
4 70
简单来说就是,找每个节点到其他节点的最长距离,并在这些最长距离中找一个最小值
#include<bits/stdc++.h>
using namespace std;
int dist[1000][1000]={0};
int G[1000][1000]={0};
int n,m;
void init(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
G[i][j]=1000000;
}
}
cin>>m;
for(int i=1;i<=m;i++){
int v1,v2,w;
cin>>v1>>v2>>w;
G[v1][v2]=w;
G[v2][v1]=w;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dist[i][j]=G[i][j];
}
}
}
void floyd(){
init();
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(dist[i][k]+dist[k][j]<dist[i][j]){
dist[i][j]=dist[i][k]+dist[k][j];
}
}
}
}
}
int find1(int v){
int m=-10000;
for(int i=1;i<=n;i++){
if(i!=v){
m=max(m,dist[v][i]);
}
}
return m;
}
void find(){
int m=1000000;
int mi=0;
for(int i=1;i<=n;i++){
int l=find1(i);
if(m>l){
m=l;
mi=i;
}
}
cout<<m<<" "<<mi;
}
void output(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<dist[i][j]<<" ";
}
cout<<endl;
}
}
int main(){
floyd();
//output();
find();
}
旅游规划
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
3 40
分析:两个权值就用两个数组保存,利用单源有权图的算法即可
#include<bits/stdc++.h>
using namespace std;
int n,m,s1,d;
int dist[10000]={0};
int value[1000]={0};
int cost[1000][1000]={0};
int len[1000][1000]={0};
int vis[1000]={0};
void create(){
cin>>n>>m>>s1>>d;
for(int i=0;i<n;i++){
dist[i]=100000;
}
for(int i=0;i<m;i++){
int l1,l2,v1,v2;
cin>>l1>>l2>>v1>>v2;
cost[l1][l2]=v2;
len[l1][l2]=v1;
}
}
void init(int s){
for(int i=0;i<n;i++){
if(i!=s&&len[s][i]){
dist[i]=len[s][i];
value[i]=cost[s][i];
}
}
}
int findmin(int s){
int mini=-1;
int m=100000;
for(int i=0;i<n;i++){
if(i!=s&&!vis[i]&&dist[i]<m){
m=dist[i];
mini=i;
}
}
return mini;
}
void find(int s){
init(s);
while(true){
int i=findmin(s);
if(i==-1)break;
vis[i]=1;
for(int j=0;j<n;j++){
if(!vis[j]&&len[i][j]){
if(dist[i]+len[i][j]<dist[j]){
dist[j]=dist[i]+len[i][j];
value[j]=value[i]+cost[i][j];
}else if(dist[i]+len[i][j]==dist[j]&&value[i]+cost[i][j]<value[j]){
value[j]=value[i]+cost[i][j];
}
}
}
}
}
int main(){
create();
find(s1);
cout<<dist[d]<<" "<<value[d];
}