[JSOI2007]重要的城市

瘦欲@ 提交于 2020-01-24 18:00:44

题目描述
参加jsoi冬令营的同学最近发现,由于南航校内修路截断了原来通向计算中心的路,导致去的路程比原先增加了近一公里。而食堂门前施工虽然也截断了原来通向计算中心的路,却没有使路程增加,因为可以找到同样长度的路作替代。其实,问题的关键在于,路截断的地方是交通要点。

同样的情况也出现在城市间的交通中。某些城市如果出了问题,可能会引起其他很多城市的交通不便。另一些城市则影响不到别的城市的交通。jsoi冬令营的同学发现这是一个有趣的问题,于是决定研究这个问题。

他们认为这样的城市是重要的:如果一个城市c被破坏后,存在两个不同的城市a和b(a, b均不等于c),a到b的最短距离增长了(或不通),则城市c是重要的。

jsoi冬令营的同学面对着一张教练组交给他们的城市间交通图,他们希望能找出所有重要的城市。现在就请你来解决这个问题。

输入格式
第一行两个整数N,M,N为城市数,M为道路数

接下来M行,每行三个整数,表示两个城市之间的无向边,以及之间的路的长度

输出格式
一行,按递增次序输出若干的数,表示重要的城市。

输入输出样例
输入 #1复制
4 4
1 2 1
2 3 1
4 1 2
4 3 2
输出 #1复制
2

N<=200,M<=1e4


很显然的思路就是枚举每个点。然后 n^4 ,TLE。

怎么只跑一次floyd呢?就是floyd 的时候,记录最短路的个数。

然后对于我们当前枚举的点 k,如果存在:g[i][j]==g[i][k]+g[k][j]&&num[i][j]==num[i][k]*num[k][j] ,那么这个点对于i,j来说就是重要点。

AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=210;
int g[N][N],num[N][N],n,m,cnt;
void floyd(){
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++){
				if(g[i][j]>g[i][k]+g[k][j]){
					g[i][j]=g[i][k]+g[k][j];
					num[i][j]=num[i][k]*num[k][j];
				}else if(g[i][j]==g[i][k]+g[k][j]){
					num[i][j]+=num[i][k]*num[k][j];
				}
			}
}
signed main(){
	cin>>n>>m;	memset(g,0x3f,sizeof g);
	for(int i=1;i<=n;i++)	g[i][i]=0;
	for(int i=1,a,b,c;i<=m;i++){
		cin>>a>>b>>c;
		g[a][b]=g[b][a]=min(g[a][b],c);
		num[a][b]=num[b][a]=1;
	}
	floyd();
	for(int k=1;k<=n;k++){
		int flag=0;
		for(int i=1;i<=n&&!flag;i++){
			for(int j=1;j<=n&&!flag;j++){
				if(i==k||j==k)	continue;
				if(g[i][j]==g[i][k]+g[k][j]&&num[i][j]==num[i][k]*num[k][j])
					flag=1;
			}
		}
		if(flag)	cnt++,cout<<k<<' ';
	}
	if(!cnt)	puts("No important cities.");
	return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!