1. 程式人生 > 其它 >【USACO 2021JAN P】Sum of Distances

【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;
}