题目大意:
(题目翻译摘自zzj大神犇,orzorzorz)
给你一张无向图,点数为
N(N<=100)
,边数为
M(M<=10000)
,起点为
S
,终点为一个集合
分析:
我们二分最小值
k
,然后每个点显然是越早到越好。
AC code:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#define ONLINE_JUDGE
typedef long long LL;
typedef double DB;
typedef long double LD;
using namespace std;
const int MAXN = 109, MAXM = 20009;
const int INF = 0x3f3f3f3f;
int n, m, h, s, e;
struct Ugraph
{
int size;
int head[MAXN];
int to[MAXM];
int t[MAXM], r[MAXM], p[MAXM];
int ne[MAXM];
Ugraph(){size = 1;}
void add_edge(int u, int v, int T, int R, int P)
{
to[size] = v, t[size] = T, r[size] = R, p[size] = P, ne[size] = head[u], head[u] = size++;
to[size] = u, t[size] = T, r[size] = R, p[size] = P, ne[size] = head[v], head[v] = size++;
}
}G;
int ext[MAXN];
int dis[MAXN];
bool vis[MAXN];
int fr[MAXN];
void spfa(int k)
{
queue<int> q;
memset(dis, INF, sizeof(dis));
memset(vis, false, sizeof(vis));
memset(fr, 0, sizeof(fr));
q.push(s), dis[s] = 0, vis[s] = true;
while(!q.empty())
{
int now = q.front();
q.pop(), vis[now] = false;
for(int i = G.head[now]; i; i = G.ne[i])
{
int to = G.to[i], r = G.r[i], p = G.p[i], t = G.t[i];
if(dis[to] > dis[now]+t && r+p*(dis[now]+t) <= k)
{
dis[to] = dis[now]+t;
fr[to] = now;
if(!vis[to])
{
vis[to] = true;
q.push(to);
}
}
}
}
}
bool check(int k)
{
spfa(k);
for(int i = 1; i <= e; ++i)
if(dis[ext[i]] < INF) return true;
return false;
}
void output(int x, int cnt)
{
if(!fr[x]) printf("%d", cnt);
if(fr[x]) output(fr[x], cnt+1);
printf(" %d", x);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu240.in", "r", stdin);
freopen("sgu240.out", "w", stdout);
#endif
scanf("%d%d%d%d%d", &n, &m, &h, &s, &e);
for(int i = 1; i <= m; ++i)
{
int u, v, t, r, p;
scanf("%d%d%d%d%d", &u, &v, &t, &r, &p);
G.add_edge(u, v, t, r, p);
}
for(int i = 1; i <= e; ++i)
scanf("%d", ext+i);
int l = 0, r = INF;
while(l < r)
{
int mid = (l+r)>>1;
if(check(mid)) r = mid;
else l = mid+1;
}
if(l > h) puts("NO");
else
{
puts("YES");
printf("%d\n", l);
check(l);
for(int i = 1; i <= e; ++i)
if(dis[ext[i]] < INF)
{
output(ext[i], 1);
break;
}
puts("");
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}