[CF416E]President‘s Path

President's Path

题解

看到n\leq 500应该就很容易想到Floyed

我们可以先通过Floyed求出最短路,对于一个点,如果它在最短路上,则一定可以作为拆分点更新这条路径。

如果暴力枚举所有点与边时会T的,由于对于一个点与它相接的最多只有n条边,我们可以考虑从这方面优化。

对于每个点,我们可以先算出它到某个点时需要使用的边,最后枚举拆分点时将它加上即可。

时间复杂度O\left(n^3 \right )

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 505
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=1e9+7;
typedef pair<int,LL> pii;
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
int n,m,f[MAXN][MAXN],g[MAXN][MAXN],cnt[MAXN],ans[MAXN][MAXN];
signed main(){
	memset(f,0x3f,sizeof(f));
	memset(g,0x3f,sizeof(g));
	read(n);read(m);
	for(int i=1;i<=n;i++)f[i][i]=0;
	for(int i=1;i<=m;i++){
		int u,v,w;read(u);read(v);read(w);
		f[u][v]=f[v][u]=g[u][v]=g[v][u]=min(f[u][v],w);
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				f[i][j]=f[j][i]=min(f[i][k]+f[k][j],f[i][j]);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)cnt[j]=0;
		for(int j=1;j<=n;j++)
			for(int k=1;k<=n;k++)
				if(f[i][k]+g[k][j]==f[i][j])cnt[j]++;
		for(int j=1;j<=n;j++)
			for(int k=1;k<=n;k++)
				if(f[i][k]+f[k][j]==f[i][j])
					ans[i][j]+=cnt[k];
	}
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)
			if(f[i][j]>INF-1)puts("0");
			else printf("%d ",ans[i][j]);
	return 0;
}

谢谢!!!

posted @ 2020-08-23 15:16  StaroForgin  阅读(14)  评论(0)    收藏  举报  来源