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();
}
}