Problem Description
TonyY是一个喜欢到处浪的男人,他的梦想是带着兰兰姐姐浪遍天朝的各个角落,不过在此之前,他需要做好规划。
现在他的手上有一份天朝地图,上面有n个城市,m条交通路径,每条交通路径都是单行道。他已经预先规划好了一些点作为旅游的起点和终点,他想选择其中一个起点和一个终点,并找出从起点到终点的一条路线亲身体验浪的过程。但是他时间有限,所以想选择耗时最小的,你能告诉他最小的耗时是多少吗?
Input
包含多组测试数据。
输入第一行包括两个整数n和m,表示有n个地点,m条可行路径。点的编号为1 - n。
接下来m行每行包括三个整数i, j, cost,表示从地点i到地点j需要耗时cost。
接下来一行第一个数为S,表示可能的起点数,之后S个数,表示可能的起点。
接下来一行第一个数为E,表示可能的终点数,之后E个数,表示可能的终点。
0<S, E≤n≤100000,0<m≤100000,0<cost≤100。
Output
输出他需要的最短耗时。
Sample Input
4 4
1 3 1
1 4 2
2 3 3
2 4 4
2 1 2
2 3 4
1 3 1
1 4 2
2 3 3
2 4 4
2 1 2
2 3 4
Sample Output
1
Source
福州大学第十四届程序设计竞赛_重现赛
思路:第一次自己做的时候用spfa把每个点都遍历一遍,然后找每个点到终点的最短路。
#include<queue> #include<algorithm> #include<stdio.h> #include<string.h> using namespace std; struct node { int x, y, s; } a[100010]; int first[100010], nextt[100010]; int n, m, e, w,ans; int sta[100010], en[100010]; int dis[100010],book[100010]; queue<int>q; void spfa(int x) { q.push(x); memset(dis,0x3f,sizeof(dis)); dis[x]=0; while(!q.empty()) { x=q.front(); book[x]=0; q.pop(); int k=first[x]; while(k>=0) { if(dis[a[k].y]>dis[a[k].x]+a[k].s) { dis[a[k].y]=dis[a[k].x]+a[k].s; if(!book[a[k].y]) { q.push(a[k].y); book[a[k].y]=1; } } k=nextt[k]; } } } int main() { while(~scanf("%d%d", &n, &m)) { ans=0x3f3f3f; memset(first, -1, sizeof(first)); memset(nextt, -1, sizeof(nextt)); for(int i = 0; i < m; i++) { scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].s); nextt[i] = first[a[i].x]; first[a[i].x] = i; } scanf("%d", &e); for(int i = 0; i < e; i++) { scanf("%d", &sta[i]); } scanf("%d", &w); for(int i = 0; i < w; i++) { scanf("%d",&en[i]); } for(int i=0;i<e;i++) { spfa(sta[i]); for(int i=0;i<w;i++) { ans=min(ans,dis[en[i]]); } } printf("%d\n",ans); } }
正解:把0点设为集合起点,n+1为集合终点,0到所有起点距离为0,所有终点到n+1的终点为0.问题就转变成了找0到n+1的最短路。
#include<stdio.h> #include<algorithm> #include<string.h> #include<queue> #define M 100010 using namespace std; int n,m; struct node { int x,y,s,nextt; }a[M]; queue<int>q; int heat[M],cut; int dis[M],vis[M]; void add(int x,int y,int s) { a[cut].y=y; a[cut].s=s; a[cut].nextt=heat[x]; heat[x]=cut++; } void spfa() { q.push(0); memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); dis[0]=0; int x,k; while(!q.empty()) { x=q.front(); q.pop(); vis[x]=0; k=heat[x]; while(k>=0) { if(dis[a[k].y]>dis[x]+a[k].s) { dis[a[k].y]=dis[x]+a[k].s; if(!vis[a[k].y]) { vis[a[k].y]=1; q.push(a[k].y); } } k=a[k].nextt; } } printf("%d\n",dis[n+1]); } int main() { int x,y,s; while(~scanf("%d%d",&n,&m)) { memset(heat,-1,sizeof(heat)); cut=0; for(int i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&s); add(x,y,s); } scanf("%d",&m); while(m--) { scanf("%d",&x); add(0,x,0); } scanf("%d",&m); while(m--) { scanf("%d",&y); add(y,n+1,0); } spfa(); } }