zoukankan      html  css  js  c++  java
  • JZOJ5771【NOIP2008模拟】遨游

    Description

         MWH寒假外出旅游,来到了S国。S国划分为N个省,第i个省有Ti座城市,编号分别为Ci1,Ci2,……CiTi(各省城市编号不会重复)。所有城市间有M条双向的道路连接,从任意一个城市出发,可到达一切城市,每条道路均须收费。
         此时恰逢春运期间,S国交通运输局采取了优惠措施。当一条路的路费在[L..R]区间时,可免去。同时,每个省也有优惠措施,第i个省内的每条道路路费收其Xi%,连接第i个省和第j个省的每条道路路费收其(Xi%+Xj%)/2。
    MWH想从城市s走到城市t,请求出一对L,R,确保:

    1. MWH能免费到达目的地;
    2. L≤R;
    3. L、R均为整数;
    4. L尽可能地大,R在满足L最大的前提下最小。



    注意:因每条道路由各省的交通运输局直接管辖,所以每条道路的路费必须先得到省级优惠,再得到国家级优惠。
     
     

    Input

    第一行两个整数N,M。
    接下来M行,每行三个整数,u、v、w,表示连接u、v的道路需收费w。
    接下来N行,第i+M+1行有一个整数Ti,后面Ti个整数,分别是Ci1..CiTi(所有城市编号保证按正整数顺序给出1..  Ti)。
    下一行N个整数X1..Xi。
    最后一行,两个整数,s、t。

    Output

    一行两个整数,如题,L和R。
     

    Sample Input

    3 7
    1 2 3
    5 2 8
    1 3 7
    5 4 5
    2 4 9
    3 5 10
    3 4 2
    2 1 2
    1 3
    2 4 5
    30 50 60
    1 5
     

    Sample Output

    2 6
    
    
    
     

    Data Constraint


     

    想到正解了但是写萎了233.

    emmmmm...二分两次,先二分l,跑spfa判断是否S与T联通。

    然后再二分r,spfa...

    其实不用spfa也行,spfa复杂度有点不好看。、

    貌似并查集可以搞一搞, 好像做过类似的题。


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    inline int read() {
        int res=0;char c=getchar();bool f=0;
        while(!isdigit(c)) {if(c=='-')f=1;c=getchar();}
        while(isdigit(c))res=(res<<3)+(res<<1)+(c^48),c=getchar();
        return f?-res:res;
    }
    #define N 50005
    #define M 200005
    int n, m, S, T;
    struct edge {
        int nxt, to, from;
        double val;
    }ed[M*2];
    int head[N], cnt;
    inline void add(int x, int y, int z)
    {
        ed[++cnt].from = x, ed[cnt].to = y;
        ed[cnt].nxt = head[x], ed[cnt].val = z;
        head[x] = cnt;
    }
    int belong[N];
    int youh[N];
    int Lans, Rans, l = 1e9, r;
    
    double dis[N];
    bool ex[N], can[M*2];
    int res;
    int pre[N];
    
    inline void spfa()
    {
        for (int i = 1 ; i < N ; i ++) dis[i] = 1e9;
        memset(ex, 0, sizeof ex);
        dis[S] = 0;
        queue <int> q;
        q.push(S);
        while(!q.empty())
        {
            int x = q.front();q.pop();
            ex[x] = 0;
            for (register int i = head[x] ; i ; i = ed[i].nxt)
            {
                if (can[i]) continue;
                int to = ed[i].to;
                if (dis[to] > dis[x] + ed[i].val)
                {
                    dis[to] = dis[x] + ed[i].val;
                    if (!ex[to]) ex[to] = 1, q.push(to);
                }
            }
        }
    }
    
    inline bool check(int mid)
    {
        memset(can, 0, sizeof can);
        for (register int i = 1 ; i <= cnt ; i ++) if (ed[i].val < (double)mid) can[i] = 1;
        spfa();
        return dis[T] != 1e9;
    }
    
    inline bool Check(int mid)
    {
        memset(can, 0, sizeof can);
        for (register int i = 1 ; i <= cnt ; i ++) 
        {
            if (ed[i].val < (double)Lans) can[i] = 1;
            if (ed[i].val > (double)mid) can[i] = 1;
        }
        spfa();
        return dis[T] != 1e9;
    }
    
    int main()
    {
    //    freopen("trip.in", "r", stdin);
    //    freopen("trip.out", "w", stdout);
        n = read(), m = read();
        for (register int i = 1 ; i <= m ; i ++)
        {
            int x = read(), y = read(), z = read();
            add(x, y, z), add(y, x, z);
        }
        for (register int i = 1 ; i <= n ; i ++)
        {
            int t = read();
            for (register int j = 1 ; j <= t ; j ++)
                belong[read()] = i;
        }
        for (register int i = 1 ; i <= n ; i ++) youh[i] = read();
        S = read(), T = read();
        for (register int i = 1 ; i <= cnt ; i ++)
        {
            int x = ed[i].from, y = ed[i].to;
            ed[i].val = (double)(((double)youh[belong[x]] + (double)youh[belong[y]]) / 200) * ed[i].val;
            r = max(r, (int)ed[i].val + 1);
            l = min(l, max((int)ed[i].val - 1, 0));
        }
        int ll = l, rr = r;
        int mid;
        while(l <= r)
        {
            mid = (l + r) >> 1;
            if (check(mid)) l = mid + 1, Lans = mid;
            else r = mid - 1;
        }
        ll = Lans;
        while(ll <= rr) 
        {
            mid = (ll + rr) >> 1;
            if (Check(mid)) rr = mid - 1, Rans = mid;
            else ll = mid + 1;
        }
        printf("%d %d
    ", Lans, Rans);
        return 0;
    }
  • 相关阅读:
    Linux下编译安装redis
    docker搭建swoole的简易的聊天室
    Linux下面安装swoole
    laravel命令
    史上最污技术解读,60 个 IT 术语我竟然秒懂了.....
    redis集群搭建
    Windows安装MongoDB
    十大经典排序算法(动图演示)
    消息中间件基础
    laravel邮件发送
  • 原文地址:https://www.cnblogs.com/BriMon/p/9443266.html
Copyright © 2011-2022 走看看