日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2019牛客暑期多校训练营(第六场)H - Train Driver (最短路)

發布時間:2024/4/18 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2019牛客暑期多校训练营(第六场)H - Train Driver (最短路) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接

題意

A、B、CA、B、CABC三個人,AAA會在集合SaSaSa中等概率出現,BBB會在結合SbSbSb中等概率出現,CCC會等概率出現在所有點上。求他們三個人回合的最小路徑和的期望

思路

  • 預處理Sa、SbSa、SbSaSb兩個集合到其他點的距離(BFS)
  • 枚舉A、B的出現的所有狀態,對每個點初始dis[i]=D[A][i]+D[B][i]dis[i] = D[A][i] + D[B][i]dis[i]=D[A][i]+D[B][i],對所有點跑最短路更新disdisdis,求得每個點作為C出現對答案的貢獻。
  • 因為所有的邊權都相同,可以用兩個隊列維護將最短路優化的O(n),另外加上基數排序,可以卡過時間
  • 枚舉狀態,得到每種狀態最長的回合距離,然后重新建圖,距離遞增建邊,每個距離對應的點建邊,最后跑BFS就行(邊權相同處理),因為每個點的的距離都增加1,所以最后要減去
  • // 做法1 #include <bits/stdc++.h> const int maxn = 1e5 + 5; const int inf = 0x3f3f3f3f; using namespace std; vector<int> g[maxn]; int D[2][30][maxn], a[30], b[30], dis[maxn]; int num[maxn<<1], Rank[maxn]; int n, m;void bfs(int s, int *d) { for (int i = 1; i <= n; ++i) {d[i] = -1;}d[s] = 0;queue<int> que;que.push(s);while (!que.empty()) {int u = que.front();que.pop();for (int i = 0; i < (int)g[u].size(); ++i) {int v = g[u][i];if (d[v] != -1) continue;d[v] = d[u] + 1;que.push(v);}} } long long solve(int x, int y) {for (int i = 1; i <= n; ++i) {dis[i] = D[0][x][i] + D[1][y][i];}for (int i = 1; i <= n+n; ++i) num[i] = 0;for (int i = 1; i <= n; ++i) num[dis[i]]++;for (int i = 1; i <= n+n; ++i) num[i] += num[i-1];for (int i = 1; i <= n; ++i) Rank[num[dis[i]]--] = i;queue<int> que1, que2;for (int i = 1; i <= n; ++i) que1.push(Rank[i]);while (!que1.empty() || !que2.empty()) {if (que2.empty() || (!que1.empty() && dis[que1.front()] < dis[que2.front()])) {int u = que1.front();que1.pop();for (int i = 0; i < (int)g[u].size(); ++i) {int v = g[u][i];if (dis[v] <= dis[u] + 1) continue;dis[v] = dis[u] + 1;que2.push(v);}}else {int u = que2.front();que2.pop();for (int i = 0; i < (int)g[u].size(); ++i) {int v = g[u][i];if (dis[v] <= dis[u] + 1) continue;dis[v] = dis[u] + 1;que2.push(v);}}}long long sum = 0;for (int i = 1; i <= n; ++i) sum += dis[i];return sum; } int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T, Case = 1;scanf("%d", &T);while (T--) {printf("Case #%d: ", Case++);scanf("%d %d", &n, &m);for (int i = 1; i <= n; ++i) g[i].clear();for (int i = 0; i < m; ++i) {int u, v;scanf("%d %d", &u, &v);g[u].push_back(v);g[v].push_back(u);}scanf("%d", &a[0]);for (int i = 1; i <= a[0]; ++i) {scanf("%d", &a[i]);bfs(a[i], D[0][i]);}scanf("%d", &b[0]);for (int i = 1; i <= b[0]; ++i) {scanf("%d", &b[i]);bfs(b[i], D[1][i]);}long long P = 0;long long Q = a[0] * b[0] * n;for (int i = 1; i <= a[0]; ++i) {for (int j = 1; j <= b[0]; ++j) {P += solve(i, j);}}long long d = __gcd(P, Q);P /= d;Q /= d;if (Q == 1) printf("%lld", P);else printf("%lld/%lld", P, Q);puts("");}return 0; } // 做法2 #include <bits/stdc++.h> const int maxn = 1e5 + 5; const int inf = 0x3f3f3f3f; using namespace std; vector<int> g[maxn]; int D[2][30][maxn], a[30], b[30], dis[maxn]; int n, m; void bfs(int s, int *d, int x) { for (int i = 1; i <= x; ++i) {d[i] = -1;}d[s] = 0;queue<int> que;que.push(s);while (!que.empty()) {int u = que.front();que.pop();for (int i = 0; i < (int)g[u].size(); ++i) {int v = g[u][i];if (d[v] != -1) continue;d[v] = d[u] + 1;que.push(v);}} } long long solve(int x, int y) {int mx = 0;for (int i = 1; i <= n; ++i) mx = max(mx, D[0][x][i] + D[1][y][i]);for (int i = n+1; i <= mx+n+1; ++i) g[i].clear();for (int i = n+1; i <= mx+n; ++i) g[i].push_back(i+1);for (int i = 1; i <= n; ++i) g[n+1+D[0][x][i]+D[1][y][i]].push_back(i);bfs(n+1, dis, mx+n+1);long long sum = 0;for (int i = 1; i <= n; ++i) sum += dis[i];return sum; } int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T, Case = 1;scanf("%d", &T);while (T--) {printf("Case #%d: ", Case++);scanf("%d %d", &n, &m);for (int i = 1; i <= n; ++i) g[i].clear();for (int i = 0; i < m; ++i) {int u, v;scanf("%d %d", &u, &v);g[u].push_back(v);g[v].push_back(u);}scanf("%d", &a[0]);for (int i = 1; i <= a[0]; ++i) {scanf("%d", &a[i]);bfs(a[i], D[0][i], n);}scanf("%d", &b[0]);for (int i = 1; i <= b[0]; ++i) {scanf("%d", &b[i]);bfs(b[i], D[1][i], n);}long long P = 0;long long Q = a[0] * b[0] * n;for (int i = 1; i <= a[0]; ++i) {for (int j = 1; j <= b[0]; ++j) {P += solve(i, j);}}long long d = __gcd(P, Q);P /= d;Q /= d;P -= Q;if (Q == 1) printf("%lld", P);else printf("%lld/%lld", P, Q);puts("");}return 0; } 與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的2019牛客暑期多校训练营(第六场)H - Train Driver (最短路)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。