sgu240:Runaway(二分+最短路)

来源:互联网 发布:下载软件管家360 编辑:程序博客网 时间:2024/05/21 07:56

题目大意:
(题目翻译摘自zzj大神犇,orzorzorz)
      给你一张无向图,点数为N(N<=100),边数为M(M<=10000),起点为S,终点为一个集合End,且|End|=E,然后对于每条边,有5个参数,Ai,Bi,Ti,Ri,Pi,分别表示边i连在Ai,Bi间,假设你到边i的一端的时候已经走过的距离为D,那么你到达另一端的时间为Ri+(D+Ti)Pi,令F[i]表示从S走到i的任意一条路径上走过的所有边中走过每条边所花费的时间的最大值最小是多少。我们令ans=min(F[i]|(iEnd)),如果ansH,则输出YES,并且输出ans,然后输出路径上的点数和路径上包含了那些点。

分析:
      我们二分最小值k,然后每个点显然是越早到越好。
      spfa并且满足Ri+(D+Ti)Pik即可。

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_JUDGEtypedef 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;}
0 0
原创粉丝点击