题目描述:
给一个n(1≤n≤2500)个点m(1≤m≤6200)条边的无向图,求s到t的最短路。
输入格式:
第一行四个由空格隔开的整数 n、m、s、t。
之后的m行,每行三个正整数si、ti、wi(1≤wi≤10^9),表示一条从si到ti长度为wi的边。
输出格式:
一个整数表示从s到t的最短路长度。数据保证至少存在一条道路。
输入输出样例
输入 #1
7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1
输出 #1
7
思路:
最短路问题,路都是双向,可用spfa或者kurskal算法去解决,下面提供一个用spfa的代码。
代码:
#include <bits/stdc++.h>
#define Pa pair< long long, int >
#define fi first
#define se second
using namespace std;
const int MaxN = 1e5 + 1;
const long long inf = 1e17 + 7;
vector< Pa > graph[ MaxN ];
bool vis[ MaxN ];
int cnt[ MaxN ];
long long dis[ MaxN ];
queue< int > que;
bool spfa( int N, int M, int S ) {
int i, j, k;
int p;
for ( i = 1; i <= N; i ++ ) {
dis[ i ] = inf;
cnt[ i ] = 0;
vis[ i ] = false;
}
dis[ S ] = 0, vis[ S ] = true, que.push( S );
while ( !que.empty( ) ) {
p = que.front( ), que.pop( ), vis[ p ] = false;
int siz = graph[ p ].size( );
for ( i = 0; i < siz; i ++ ) {
int to = graph[ p ][ i ].fi, va = graph[ p ][ i ].se;
if ( dis[ to ] > dis[ p ] + va ) {
dis[ to ] = dis[ p ] + graph[ p ][ i ].se;
cnt[ to ] = cnt[ p ] + 1;
if ( cnt[ to ] >= N ) {
return true;
}
if ( !vis[ to ] ) {
que.push( to );
vis[ to ] = true;
}
}
}
}
return false;
}
int main( ) {
int i, j, k;
int N, M, S, T;
int from, to, value;
Pa temp;
scanf("%d%d%d%d", &N, &M, &S, &T);
for ( i = 1; i <= M; i ++ ) {
scanf("%d %d %d", &from, &to, &value );
temp.se = value;
temp.fi = to;
graph[ from ].push_back( temp );
temp.fi = from;
graph[ to ].push_back( temp );
}
spfa( N, M, S );
cout<<dis[T];
}