2019牛客暑期多校训练营(第六场) H:Train Driver (最短路+概率)
题意:给定无向图,Alice在A集合选一个点,Bob在B集合选一个点,CXK在全集里选择一个点。 然后问“三人到某一点集合打篮球的最小距离”的期望。
思路:做过一个裸题,就是给定三人位置,问去哪里集合距离代价最小。 那题就是三个点跑三次SPFA,就可以更新答案了。而此题有一个Cxk,非常的头疼,然而注意到边权为1,tm的不是直接BFS扩展就可以了吗。枚举Alice和Bob的位置,然后dis[i]=disA[i]+disB[j],然后就可以扩展了。 注意不要带log就可以过这题了,排序可以用基数排序,然后维护两个单调队列,每次取小的一个队首进行扩展。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=200010; const int inf=1e9; int disA[21][maxn],disB[21][maxn],a[maxn],b[maxn]; int Laxt[maxn],Next[maxn],To[maxn],cnt,N; ll sum; void add(int u,int v) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; } void BFS(int dis[],int st) { rep(i,1,N) dis[i]=inf; dis[st]=0; queue<int>q; q.push(st); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=Laxt[u];i;i=Next[i]){ if(dis[To[i]]==inf){ dis[To[i]]=dis[u]+1; q.push(To[i]); } } } } int num[maxn],c[maxn],dis[maxn]; void solve() //基数排序+两个单调队列 { rep(i,0,N+N) num[i]=0; rep(i,0,N) num[dis[i]]++,d[i]=0; rep(i,1,N+N) num[i]+=num[i-1]; rep(i,1,N) c[num[dis[i]]--]=i; queue<int>q1,q2; rep(i,1,N) q1.push(c[i]); while(!q1.empty()||!q2.empty()){ if(q2.empty()||(!q1.empty()&&!q2.empty()&&dis[q1.front()]<dis[q2.front()])) { int u=q1.front(); q1.pop(); for(int i=Laxt[u];i;i=Next[i]) { if(dis[To[i]]>dis[u]+1) { dis[To[i]]=dis[u]+1; q2.push(To[i]); } } } else { int u=q2.front(); q2.pop(); for(int i=Laxt[u];i;i=Next[i]) { if(dis[To[i]]>dis[u]+1) { dis[To[i]]=dis[u]+1; q2.push(To[i]); } } } } rep(i,1,N) sum+=dis[i]; } int main() { int C=0,T,M,A,B,u,v; scanf("%d",&T); while(T--){ scanf("%d%d",&N,&M); rep(i,1,N) Laxt[i]=0; cnt=0; rep(i,1,M){ scanf("%d%d",&u,&v); add(u,v); add(v,u); } scanf("%d",&A); rep(i,1,A) scanf("%d",&a[i]); scanf("%d",&B); rep(i,1,B) scanf("%d",&b[i]); rep(i,1,A) BFS(disA[i],a[i]); rep(i,1,B) BFS(disB[i],b[i]); sum=0; rep(i,1,A) rep(j,1,B){ rep(k,1,N) dis[k]=disA[i][k]+disB[j][k]; solve(); } ll ans=1LL*A*B*N; ll g=__gcd(ans,sum); printf("Case #%d: ",++C); if(g==sum) printf("%lld\n",sum/g); else printf("%lld/%lld\n",sum/g,ans/g); } return 0; }
It is your time to fight!