遨遊 9.22模擬賽
阿新 • • 發佈:2018-12-11
題目大意:
N個省M條路,然後每個省有一些城市,M條路連線著兩座城市(保證是連通圖),有什麼省級優惠:連線一個省中的兩個城市的路費得到xi%的優惠,連線兩個省的路得到(xi% + xj%) / 2的優惠,還有什麼國家級優惠,如果這個價格在L—R之間則免費,問L & R的大小
解題思路:
dfs + 二分巢狀 二分出 L & R,判斷條件是滿足(價格>=L && 價格<R)的情況下可以從S到T,滿足則不斷將L弄大,否則弄小 R同理
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rep(i, a, b, c) for(register int i = a; b; i = c)
#define r(i, a, b) for (register int i = a; i <= b; i++)
#define f(i, a, b) for (register int i = a; i >= b; i--)
using namespace std;
struct SPFA {
int to, next;
double w;
}e[500001];
int cnt, N, M, last[200001], s, t;
int n, QWERTYUIOP, u[200001], v[200001], a[200001];
double w[200001], X[200001];//別管那個QWERTYUIOP
double pt(double x) { return x * 0.01; }//x%
inline void add(int u, int v, double w) {
e[++cnt].to = v; e[cnt].w = w;
e[cnt].next = last[u]; last[u] = cnt;
e[++cnt].to = u; e[cnt].w = w;
e[cnt] .next = last[v]; last[v] = cnt;
}//雙向邊
bool dfs(int now, int low, int high) {
//dfs判斷是否有一條路徑上每一條路的路費都 low<= <high
if (now == t) return 1;//已經到了
if (v[now]) return 0;//走過就不走了
v[now] = 1;//標記
rep(i, last[now], i, e[i].next)//列舉邊
if (e[i].w >= (double)low && e[i].w < (double)high)
//判斷路費是否滿足條件
if (dfs(e[i].to, low, high)) return 1;
//接著搜
return 0;
}
int main() {
scanf("%d%d", &N, &M);
r(i, 1, M) scanf("%d%d%lf", &u[i], &v[i], &w[i]);
r(i, 1, N) {
scanf("%d", &n);
r(j, 1, n)
scanf("%d", &QWERTYUIOP),
a[QWERTYUIOP] = i;
}
r(i, 1, N) scanf("%lf", &X[i]);
scanf("%d%d", &s, &t);
r(i, 1, M) {
double rz = 0;
if (a[u[i]] != a[v[i]])
rz = (pt(X[a[u[i]]]) + pt(X[a[v[i]]])) / 2.0 * (double)w[i];
else rz = pt((double)X[a[u[i]]]) * (double)w[i];
add(u[i], v[i], rz);//建圖
}
int L = 0, R = 15000, L1 = 0, R1 = 0, mid1, mid2;
while (L <= R) {//二分
mid1 = (L + R) >> 1;
int l = mid1, r = 15000;
bool ok = 0;
memset(v, 0, sizeof(v));//初始化
if (dfs(s, mid1, 2e5)) {
while (l <= r) {//巢狀
memset(v, 0, sizeof(v));//初始化
mid2 = (l + r) >> 1;
if (dfs(s, mid1, mid2)) {//判斷是否滿足條件的路徑
ok = 1;
L1 = mid1; R1 = mid2;//記錄下答案
r = mid2 - 1;
} else l = mid2 + 1;
}
}
if (ok) L = mid1 + 1;
else R = mid1 - 1;//常規二分
}
printf("%d %d", L1, R1);
}