1. 程式人生 > >遨遊 9.22模擬賽

遨遊 9.22模擬賽

題目大意:

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); }