C - 草儿是个路痴
虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,0),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。
Input
输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。
Output
输出草儿能去某个喜欢的城市的最短时间。
Sample Input
6 2 3
1 3 5
1 4 7
2 8 12
3 8 4
4 9 12
9 10 2
1 2
8 9 10
Sample Output
9
题解
题目意思就是有S个起点,D个终点,求起点到终点所有路径中的最短路。
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int maxe = 100100, maxv = 1100;
const int INF = unsigned(-1) >> 1;
int m, s, n;
struct edge
{
int x, y;
};
edge es[maxe]; //边
struct Graph
{
int dis;
};
Graph G[maxv][maxv]; //邻接矩阵
struct dist
{
int dis;
};
dist d[maxv]; //最短路径
void fun(int s)
{
while (true)
{
bool updata = false;
for (int i = 0; i < m; i++) //遍历所有的边
{
edge e = es[i];
if (d[e.x].dis != INF) //如果遍历过e.x点
{
if (d[e.x].dis + G[e.x][e.y].dis < d[e.y].dis) //如果从e.x点走到e.y点的路径 比 其他点走到e.y的路径要短
{
d[e.y].dis = d[e.x].dis + G[e.x][e.y].dis; //更新e.y的路径为更短的
updata = true;
}
}
if (d[e.y].dis != INF) //如果遍历过e.y点
{
if (d[e.y].dis + G[e.x][e.y].dis < d[e.x].dis) //如果从e.y点走到e.x点的路径 比 其他点走到e.x的路径要短
{
d[e.x].dis = d[e.y].dis + G[e.x][e.y].dis; //更新e.x的路径为更短的
updata = true;
}
}
}
if (updata == false) //如果所有的边都遍历过了,路径信息没有更新过,说明已经遍历完了,结束搜索
break;
}
}
int main()
{
while (scanf("%d%d%d", &m, &s, &n) != EOF)
{
int dis;
for (int i = 1; i < maxv; i++) //初始化邻接矩阵
for (int j = 1; j < maxv; j++)
G[i][j].dis = INF;
for (int i = 0; i < m; i++)
{
scanf("%d%d%d", &es[i].x, &es[i].y, &dis);
if (dis < G[es[i].x][es[i].y].dis) //构建邻接矩阵
G[es[i].x][es[i].y].dis = G[es[i].y][es[i].x].dis = dis;
}
for (int i = 0; i < maxv; i++) //初始化最短距离
d[i].dis = INF;
int city[maxv];
for (int i = 0, x; i < s; i++) //草儿的邻居
{
scanf("%d", &x);
d[x].dis = 0;
}
for (int i = 0; i < n; i++) //草儿喜欢的城市
scanf("%d", city + i);
int ans = INF;
fun(0);
for (int i = 0; i < n; i++)
{
ans = min(ans, d[city[i]].dis);
}
printf("%d\n", ans);
}
return 0;
}
D - 稀的泥和热的油
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
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
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
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
题解
就一个基本的单源最短路,上Bellman-Ford算法 !
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int maxe = 100100, maxv = 1100;
const int INF = unsigned(-1) >> 1;
int n, m, s, t;
struct edge
{
int x, y;
};
edge es[maxe];
struct Graph
{
int dis;
};
Graph G[maxv][maxv];
struct dist
{
int dis;
};
dist d[maxv];
void fun(int s)
{
for (int i = 0; i < n; i++)
d[i].dis = INF;
d[s].dis = 0;
while (true)
{
bool updata = false;
for (int i = 0; i < m; i++) //遍历所有的边
{
edge e = es[i];
if (d[e.x].dis != INF) //如果遍历过e.x点
{
if (d[e.x].dis + G[e.x][e.y].dis < d[e.y].dis) //如果从e.x点走到e.y点的路径 比 其他点走到e.y的路径要短
{
d[e.y].dis = d[e.x].dis + G[e.x][e.y].dis; //更新e.y的路径为更短的
updata = true;
}
}
if (d[e.y].dis != INF) //如果遍历过e.y点
{
if (d[e.y].dis + G[e.x][e.y].dis < d[e.x].dis) //如果从e.y点走到e.x点的路径 比 其他点走到e.x的路径要短
{
d[e.x].dis = d[e.y].dis + G[e.x][e.y].dis; //更新e.x的路径为更短的
updata = true;
}
}
}
if (updata == false) //如果所有的边都遍历过了,路径信息没有更新过,说明已经遍历完了,结束搜索
break;
}
}
int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
int dis;
if (n == 0 && m == 0)
break;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
G[i][j].dis = INF;
for (int i = 0; i < m; i++)
{
scanf("%d%d%d", &es[i].x, &es[i].y, &dis);
if (dis < G[es[i].x][es[i].y].dis)
G[es[i].x][es[i].y].dis = G[es[i].y][es[i].x].dis = dis;
}
scanf("%d%d", &s, &t);
fun(s);
if (d[t].dis == INF)
puts("-1");
else
printf("%d\n", d[t].dis);
}
return 0;
}