畅通工程续
http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1001&cid=12497&hide=0
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 23 Accepted Submission(s) : 8
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
Input
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
Output
Sample Input
3 3 0 1 1 0 2 3 1 2 1 0 2 3 1 0 1 1 1 2
Sample Output
2 -1
Author
Source
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
using namespace std ;
#define N 205
#define inf 10000000
int dis[N] ;
int vis[N] ;
int map[N][N] ;
int n , m ;
void init ( )
{
for( int i = 0 ; i < n ; i++ )
for( int j = 0 ; j < n ; j++ )
if( i== j )
map[i][j] = 0;
else
map[i][j] = inf ;
}
void dijkstra ( int v )
{
memset( vis , 0 , sizeof( vis ) ) ;
vis[v] = 1 ;
for( int i = 0 ; i < n ; i ++ )
dis[i] = map[v][i] ;
int num = 1 ;
while( num < n )
{
int min = inf , k ;
num++ ;
for( int i = 0 ; i < n ; i++ )
if( !vis[i] && min > dis[i] )
{
k = i ;
min = dis[i] ;
}
vis[k] = 1 ;
for( int i = 0 ; i < n ; i++ )
if( (!vis[i])&&map[k][i] < inf ){
if( dis[i] > ( dis[k] + map[k][i] ) )
dis[i] = dis[k] + map[k][i] ;
}
}
}
int main ()
{
while( scanf("%d %d" , &n , &m )==2)
{
init();
while( m-- )
{
int a , b , c ;
scanf("%d%d%d" , &a ,&b ,&c );
if( map[a][b] > c )
map[a][b] = map[b][a] = c ;
}
int b , e ;
scanf("%d%d" ,&b ,&e );
dijkstra( b );
if( dis[e] == inf )
puts( "-1");
else
printf("%d\n" , dis[e] );
}
return 0 ;
}
using namespace std;
const int maxnum=205;
const int maxint=9999999;
int map[maxnum][maxnum];
int n,m; //城镇和道路数
void floyd(){
int i,j,k;
for(k=0;k<n;k++)
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if( map[i][k]+map[k][j]<map[i][j])
map[i][j]=map[i][k]+map[k][j];
}
void init(){
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
if(i==j) map[i][j]=0;
else
map[i][j]=maxint;
}
}
int main(){
int a,b,x;
while(scanf("%d%d",&n,&m)!=EOF){
init();
for(int i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&x);
if(x<map[a][b])
map[a][b]=map[b][a]=x;
}
floyd();
int s,t; //始点和终点
scanf("%d%d",&s,&t);
if(map[s][t]<maxint)
printf("%d\n",map[s][t]);
else
puts("-1");
}
return 0;
}
using namespace std;
const int maxnum = 205;
const int maxint = 999999;
void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
{
bool s[maxnum]; // 判断是否已存入该点到S集合中
for(int i=1; i<=n; ++i)
{
dist[i] = c[v][i];
s[i] = 0; // 初始都未用过该点
if(dist[i] == maxint)
prev[i] = 0;
else
prev[i] = v;
}
dist[v] = 0;
s[v] = 1;
// 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
// 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
for(int i=2; i<=n; ++i)
{
int tmp = maxint;
int u = v;
// 找出当前未使用的点j的dist[j]最小值
for(int j=1; j<=n; ++j)
if((!s[j]) && dist[j]<tmp)
{
u = j; // u保存当前邻接点中距离最小的点的号码
tmp = dist[j];
}
s[u] = 1; // 表示u点已存入S集合中
// 更新dist
for(int j=1; j<=n; ++j)
if((!s[j]) && c[u][j]<maxint)
{
int newdist = dist[u] + c[u][j];
if(newdist < dist[j])
{
dist[j] = newdist;
prev[j] = u;
}
}
}
}
int main()
{
//freopen("input1.txt", "r", stdin);
// 各数组都从下标1开始
int dist[maxnum]; // 表示当前点到源点的最短路径长度
int prev[maxnum]; // 记录当前点的前一个结点
int c[maxnum][maxnum]; // 记录图的两点间路径长度
int n, line; // 图的结点数和路径数
int s, t;
while(scanf("%d %d", &n, &line) != EOF)
{
int p, q, len; // 输入p, q两点及其路径长度
// 初始化c[][]为maxint
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
{
if(i == j)
c[i][j] = 0;
else
c[i][j] = maxint;
}
for(int i=1; i<=line; ++i)
{
cin >> p >> q >> len;
if(len < c[p+1][q+1])
{
c[p+1][q+1] = len; // p指向q
c[q+1][p+1] = len; // q指向p,这样表示无向图
}
}
cin >> s >> t;
for(int i=1; i<=n; ++i)
dist[i] = maxint;
Dijkstra(n, s+1, dist, prev, c);
// 最短路径长度
if(dist[t+1] != maxint)
cout << dist[t+1] << endl;
else
cout << -1 << endl;
}
return 0;
}