5771. 【NOIP2008模拟】遨游
(File IO): input:trip.in output:trip.out
Time Limits:
2000 ms Memory Limits: 262144 KB Detailed Limits
Goto ProblemSet
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,确保:
注意:因每条道路由各省的交通运输局直接管辖,所以每条道路的路费必须先得到省级优惠,再得到国家级优惠。
此时恰逢春运期间,S国交通运输局采取了优惠措施。当一条路的路费在[L..R]区间时,可免去。同时,每个省也有优惠措施,第i个省内的每条道路路费收其Xi%,连接第i个省和第j个省的每条道路路费收其(Xi%+Xj%)/2。
MWH想从城市s走到城市t,请求出一对L,R,确保:
- MWH能免费到达目的地;
- L≤R;
- L、R均为整数;
- 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。
接下来M行,每行三个整数,u、v、w,表示连接u、v的道路需收费w。
接下来N行,第i+M+1行有一个整数Ti,后面Ti个整数,分别是Ci1..CiTi(所有城市编号保证按正整数顺序给出1..
下一行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
![](https://i-blog.csdnimg.cn/blog_migrate/fe298b1f1d3814e61a11a2419ee7c878.png)
做法:分别二分枚举L,R咯┑( ̄Д  ̄)┍。
代码如下:
View Code
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }