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.. 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\n", Lans, Rans); return 0; }