【USACO 2021JAN P】Sum of Distances
【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;
}