题意:N个城市M个人K条单向边,每个人的速度不同,且在一些城市中。求到达终点时用时最少的人的编号。当用时相同时速度大的优先,速度也相同时编号大优先。
建反向边以终点为源点跑一次spfa即可。因为求的是时间,开始是把时间放在spfa的松弛里面更新的,,但其实T = S / V,求出S(dis)也就求出了时间,我的蠢愚。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 305;
const int inf = 0x3f3f3f3f;
struct node{
int to, nxt;
double w;
}e[5005];
struct pp{
double d, tt;
int id;
}ans[N];
int cnt;
int head[N];
double dis[N];
int n, m, k;
double sped[N];
int p[N];
int vis[N];
void add( int u, int v, double w )
{
e[cnt].to = v;
e[cnt].w = w;
e[cnt].nxt = head[u];
head[u] = cnt++;
}
void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
}
int cmp(pp q, pp w)
{
if( q.tt < w.tt )
return 1;
else if( q.tt == w.tt )
{
if( q.d > w.d )
return 1;
else if( q.d == w.d && q.id > w.id )
return 1;
}
return 0;
}
void spfa( int st )
{
memset(vis, 0, sizeof(vis));
for( int i = 1; i <= n; i++ )
dis[i] = inf;
queue<int> q;
while( !q.empty() )
q.pop();
q.push(st);
vis[st] = 1;
dis[st] = 0;
while( !q.empty() )
{
int now = q.front();
q.pop();
vis[now] = 0;
for( int i = head[now]; ~i; i = e[i].nxt )
{
int to = e[i].to;
if( dis[to] > dis[now] + e[i].w )
{
dis[to] = dis[now] + e[i].w;
if ( !vis[to] )
{
vis[to] = 1;
q.push(to);
}
}
}
}
}
int main()
{
while(~scanf("%d%d%d", &n, &m, &k))
{
init();
int u, v;
double w;
while(k--)
{
scanf("%d%d%lf", &u, &v, &w);
add(v, u, w);
}
int ed;
scanf("%d", &ed);
for( int i = 1; i <= m; i++ )
{
scanf("%d", &p[i]);
}
for( int i = 1; i <= m; i++ )
{
scanf("%lf", &sped[i]);
}
spfa(ed);
for( int i = 1; i <= m; i++ )
{
ans[i].id = i;
if( dis[ p[i] ] == inf )
ans[i].d = ans[i].tt = inf;
else
{
ans[i].d = dis[p[i]];
ans[i].tt = ans[i].d / sped[i];
}
}
sort(ans+1, ans+m+1, cmp);
if( ans[1].tt >= inf )
puts("No one");
else
printf("%d\n", ans[1].id);
}
return 0;
}