JZOJ 5771. 【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


 
做法:分别二分枚举L,R咯┑( ̄Д  ̄)┍。
代码如下:
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <cmath>
  5 #include <queue>
  6 #define M 500007
  7 #define N 200007
  8 using namespace std;
  9 struct edge
 10 {
 11     int to, next;
 12     double val;
 13 }e[N];
 14 int n, m, ls[N], x[N], y[N], t[N], start, end, tot, tma, tin = 10000007, l, r, dis[N], L, R, ans1, ans2;
 15 double z[N], cut[N];
 16 bool v[N], b[N];
 17 queue<int> q;
 18 
 19 void add(int u, int v, double w)
 20 {
 21     e[++tot].to = v;
 22     e[tot].next = ls[u];
 23     e[tot].val = w;
 24     ls[u] = tot;
 25     e[++tot].to = u;
 26     e[tot].next = ls[v];
 27     e[tot].val = w;
 28     ls[v] = tot;
 29 }
 30 
 31 void init()
 32 { 
 33     scanf("%d%d", &n, &m);
 34     for (int i = 1; i <= m; i++)
 35         scanf("%d%d%lf", &x[i], &y[i], &z[i]);
 36     for (int i = 1; i <= n; i++)
 37     {
 38         int T, u;
 39         scanf("%d", &T);
 40         for (int j = 1; j <= T; j++)
 41             scanf("%d", &u), t[u] = i;
 42     }
 43     for (int i = 1; i <= n; i++)
 44         scanf("%lf", &cut[i]), cut[i] /= 100;
 45     scanf("%d%d", &start, &end);
 46     for (int i = 1; i <= m; i++)
 47     {
 48         if (t[x[i]] != t[y[i]])
 49         {
 50             add(x[i], y[i], z[i] * ((cut[t[x[i]]] + cut[t[y[i]]]) / 2));
 51             tin = min(tin, (int)(z[i] * ((cut[t[x[i]]] + cut[t[y[i]]]) / 2)));
 52             tma = max(tma, (int)(z[i] * ((cut[t[x[i]]] + cut[t[y[i]]]) / 2)));
 53         }
 54         else
 55         {
 56             add(x[i], y[i], z[i] * cut[t[x[i]]]);
 57             tin = min(tin, (int)(z[i] * ((cut[t[x[i]]] + cut[t[y[i]]]) / 2)));
 58             tma = max(tma, (int)(z[i] * ((cut[t[x[i]]] + cut[t[y[i]]]) / 2)));
 59         }
 60     }
 61 }
 62 
 63 bool check(int judge1, int judge2)
 64 {
 65     memset(v, 0, sizeof(v));
 66     for (int i = 1; i <= tot; i++)
 67         if (e[i].val >= judge1 && e[i].val <= judge2) v[i] = 1;
 68     memset(b, 0, sizeof(b));
 69     memset(dis, 0x7f7f7f7f, sizeof(dis));
 70     dis[start] = 0;
 71     q.push(start);
 72     b[start] = 1;
 73     while (!q.empty())
 74     {
 75         int now = q.front();
 76         q.pop();
 77         for (int i = ls[now]; i; i = e[i].next)
 78         {
 79             if (!v[i])    continue;
 80             if (dis[now] + 1 >= dis[e[i].to])    continue;
 81             dis[e[i].to] = dis[now] + 1;
 82             if (b[e[i].to])    continue;
 83             q.push(e[i].to);
 84             b[e[i].to] = 1;
 85         }
 86         b[now] = 0;
 87     }
 88     if (dis[end] != 0x7f7f7f7f)    return 1;
 89     return 0;
 90 }
 91 
 92 void work()
 93 {
 94     l = tin, r = tma + 1;
 95     while (l < r)
 96     {
 97         int mid = (l + r + 1) / 2;
 98         if (check(mid, tma + 1))    l = mid;
 99         else r = mid - 1;
100     }
101     L = l;
102     l = tin, r = tma + 1;
103     while (l < r)
104     {
105         int mid = (l + r) / 2;
106         if (check(L, mid))    r = mid;
107         else l = mid + 1;
108     }
109     R = l;
110     printf("%d %d", L, R);
111 }
112 
113 int main()
114 {
115     freopen("trip.in", "r", stdin);
116     freopen("trip.out", "w", stdout);
117     init();
118     work();
119 }
View Code

猜你喜欢

转载自www.cnblogs.com/traveller-ly/p/9461195.html
今日推荐