【USACO 2021JAN P】Sum of Distances
阿新 • • 發佈:2021-08-19
最短路
【USACO 2021JAN P】Sum of Distances
by AmanoKumiko
Description
給出\(K\)個圖\(G1,G2...Gk\),可能有自環,但無重邊
新建一個圖\(G\),源點為\((1,1...1)\),對於圖\(G\)中的\((x1,x2...xk)\)和\((y1,y2...yk)\),若\(xi\)和\(yi\)在\(Gi\)中有連邊,則它們在\(G\)中有連邊
求源點到\(G\)中每個點的最短路之和
Input
第一行\(K\),圖的數量
每個圖的第一行包含\(N\),\(M\),以下是\(M\)條邊
Output
答案,對\(10^9+7\)取模
Sample Input
3
4 4
1 2
2 3
3 1
3 4
6 5
1 2
2 3
3 4
4 5
5 6
7 7
1 2
2 3
3 4
4 5
5 6
6 7
7 1
Sample Output
706
Data Constraint
\(∑N<=100000\),\(∑M<=200000\),\(∑K<=50000\)
Solution
觀察到從源點到某個點一定是,距離短的點先到,然後反覆橫跳,直到距離大的點到達
因此,只有最短路奇偶性相同的點才和源點連通
同時,\(G\)中某個點的最短路徑應該是它所含各點的最短路的最大值
那麼對\(K\)個圖做\(bfs\),求出每個點的奇/偶最短路
然後對路徑長排序,分奇偶隨便維護一下即可
但是對於奇偶最短路同時存在的點,它的貢獻可能有不合法的情況
如兩個點的最短路:
奇:5 7 偶:4 2
所以將奇偶最短路的最大值排序,按同樣的方式算貢獻,減去即可
PS:調題時因為模數習慣性寫的998244353調了1h///
Code
#include<bits/stdc++.h> using namespace std; #define F(i,a,b) for(int i=a;i<=b;i++) #define Fd(i,a,b) for(int i=a;i>=b;i--) #define mo 1000000007 #define LL long long #define K 50010 #define N 300010 vector<int>e[N]; struct node{int pos,val,kind;}p[N]; struct mode{int pos,kind;}; queue<mode>q; int k,n,m,u,v,dis[N][3],cnt,tot[K][3],in[3],inf; LL mul[3]={1,1,1},ans; bool vis[N][3]; void bfs(){ memset(dis,127,sizeof(dis)); inf=dis[0][0]; memset(vis,0,sizeof(vis)); q.push((mode){1,0});vis[1][0]=1;dis[1][0]=0; while(!q.empty()){ mode now=q.front();q.pop(); if(e[now.pos].size()){ F(j,0,e[now.pos].size()-1){ int go=e[now.pos][j]; if(!vis[go][1-now.kind]){ vis[go][1-now.kind]=1; dis[go][1-now.kind]=dis[now.pos][now.kind]+1; q.push((mode){go,1-now.kind}); } } } } } bool cmp(node a,node b){return a.val<b.val;} LL mi(LL x,LL y){ if(y==1)return x; return y%2?x*mi(x*x%mo,y/2)%mo:mi(x*x%mo,y/2); } int main(){ scanf("%d",&k); F(i,1,k){ scanf("%d%d",&n,&m); F(j,1,n)e[j].clear(); F(j,1,m){ scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } bfs(); F(j,1,n){ if(dis[j][0]<inf)p[++cnt]=(node){i,dis[j][0],0}; if(dis[j][1]<inf)p[++cnt]=(node){i,dis[j][1],1}; if(max(dis[j][0],dis[j][1])<inf)p[++cnt]=(node){i,max(dis[j][0],dis[j][1]),2}; } } memset(vis,0,sizeof(vis)); sort(p+1,p+cnt+1,cmp); F(i,1,cnt){ if(p[i].val==inf)break; LL dec=vis[p[i].pos][p[i].kind]?1:0; if(in[p[i].kind]-dec>=k-1){ dec=max(tot[p[i].pos][p[i].kind],1); if(p[i].kind<2)(ans+=p[i].val*mul[p[i].kind]%mo*mi(dec,mo-2)%mo)%=mo; else ans=(ans-p[i].val*mul[p[i].kind]%mo*mi(dec,mo-2)%mo+mo)%mo; } if(tot[p[i].pos][p[i].kind])(mul[p[i].kind]*=mi(tot[p[i].pos][p[i].kind],mo-2))%=mo; tot[p[i].pos][p[i].kind]++; (mul[p[i].kind]*=tot[p[i].pos][p[i].kind])%=mo; if(!vis[p[i].pos][p[i].kind])in[p[i].kind]++,vis[p[i].pos][p[i].kind]=1; } printf("%lld",ans); return 0; }