2019nc#6
https://ac.nowcoder.com/acm/contest/886#question
题号 | 标题 | 已通过代码 | 题解/讨论 | 通过率 | 团队的状态 |
---|---|---|---|---|---|
A | Garbage Classification | 点击查看 | 进入讨论 | 972/1543 | 通过 |
B | Shorten IPv6 Address | 点击查看 | 进入讨论 | 541/4388 | 通过 |
C | Palindrome Mouse | 点击查看 | PAM | 43/206 | yzj补了 |
D | Move | 点击查看 | 进入讨论 | 465/3911 | 通过 |
E | Androgynos | 点击查看 | 进入讨论 | 116/532 | 通过 |
F | K-ary Heap | 点击查看 | 进入讨论 | 8/34 | 未通过 |
G | Is Today Friday? | 点击查看 | 蔡勒公式,去重暴力 | 71/779 | 👌 |
H | Train Driver | 点击查看 | 进入讨论 | 5/26 | |
I | Can They Go to Galar? | 点击查看 | 进入讨论 | 3/23 | 未通过 |
J | Upgrading Technology | 点击查看 | 进入讨论 | 554/3837 | 通过 |
H Train Driver
题意
有一个边权都为1的无向图,有三个人,A只会出现在sa集合的点中,B只会出现在sb集合点中。C可以等概率出现在任意点。
问三个人走到同一个点的总路程的期望。
思路
每个点在固定sa,sb的情况下,dd[i] = dis[sa][i] + dis[sb][i]。
然后就是用dd[i]取更新其他点。
需要利用桶排序的思想,还要运用两个队列去优化
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include <bits/stdc++.h> using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; /**********showtime************/ const int maxn = 1e5+9; vector<int>sa, sb; vector<int>mp[maxn]; ll gcd(ll a, ll b) { if(b == 0) return a; return gcd(b, a % b); } ll sum = 0; int dis[2][22][maxn]; int n,m; void bfs(int s, int id, int flag){ queue<int>que; dis[flag][id][s] = 0; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); for(int v : mp[u]) { if(dis[flag][id][v] > dis[flag][id][u] + 1) { dis[flag][id][v] = dis[flag][id][u] + 1; que.push(v); } } } } int dd[maxn]; void dji() { priority_queue <pii> que; for(int i=1; i <=n; i++) que.push(pii(-dd[i], i)); while(!que.empty()) { pii t = que.top(); que.pop(); int u = t.se, f = -1*t.fi; if(dd[u] < f) continue; for(int v : mp[u]) { if(dd[v] > dd[u] + 1) { dd[v] = dd[u] + 1; que.push(pii(-dd[v], v)); } } } } queue<pii>que1,que2; queue<int>lev[maxn * 2]; void solve(int s1, int s2) { // cout<<s1<<" ,, " << s2<<endl; int mx = 0; for(int i=1; i<=n; i++) { dd[i] = dis[0][s1][i] + dis[1][s2][i]; lev[dd[i]].push(i); mx = max(mx, dd[i]); } for(int i=0; i <= mx; i++) { while(!lev[i].empty()) { int u = lev[i].front(); lev[i].pop(); que1.push(pii(i, u)); } } while(!que1.empty() || !que2.empty()) { pii t1 = pii(inf, inf), t2 = pii(inf, inf); if(!que1.empty()) t1 = que1.front(); if(!que2.empty()) t2 = que2.front(); if(t1.fi < t2.fi) { que1.pop(); int u = t1.se; if(dd[u] < t1.fi) continue; for(int v : mp[u]) { if(dd[v] > dd[u] + 1) { dd[v] = dd[u] + 1; que2.push(pii(dd[v], v)); } } } else { que2.pop(); int u = t2.se; if(dd[u] < t2.fi) continue; for(int v : mp[u]) { if(dd[v] > dd[u] + 1) { dd[v] = dd[u] + 1; que2.push(pii(dd[v], v)); } } } } while(!que2.empty()) { pii t2 = que2.front(); que2.pop(); int u = t2.se; if(dd[u] < t2.fi) continue; for(int v : mp[u]) { if(dd[v] > dd[u] + 1) { dd[v] = dd[u] + 1; que2.push(pii(dd[v], v)); } } } for(int i=1; i<=n; i++) sum = sum + dd[i]; } int main(){ int T; scanf("%d", &T); int cas = 0; while(T--) { scanf("%d%d", &n, &m); memset(dis, inf, sizeof(dis)); for(int i=1; i<=n; i++) mp[i].clear(); for(int i=1; i<=m; i++) { int u,v; scanf("%d%d", &u, &v); mp[u].pb(v); mp[v].pb(u); } int c1; scanf("%d", &c1); for(int i=1; i<=c1; i++) { int x; scanf("%d", &x); bfs(x, i, 0); } int c2; scanf("%d", &c2); for(int i=1; i<=c2; i++) { int x; scanf("%d", &x); bfs(x, i, 1); } sum = 0; for(int i=1; i <= c1; i++) { for(int j=1; j<=c2; j++) { solve(i, j); } } ll base = 1ll*c1*c2*n; ll gg = gcd(sum, base); printf("Case #%d: %lld/%lld\n", ++cas, sum/gg, base/gg); } return 0; }
skr