[JSOI2007]重要的城市(x)

Posted Mrsrz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JSOI2007]重要的城市(x)相关的知识,希望对你有一定的参考价值。

题目:洛谷P1841。

题目大意:如果一个城市c在城市a到b($a\neq b\neq c$)的最短路中,并且去掉c最短路就会变短,那么称c为重要的城市。

现在要你按次序输出所有重要的城市。如果没有,输出“No important cities.”(引号不必输出)。

解题思路:跑Floyd,并记录两点间的一个重要的城市。

如果两个点的距离更新,则重要的城市也更新。

如果两个点的距离在计算时出现与原来结果相等时,就说明可能出现多条最短路,这时删掉重要的城市。

最后枚举两个点,把它们之间的重要的城市去重后记录下来,排序输出即可。

由于在Floyd中,对于每个中点,其他点对都进行过考虑,因此答案是不会出现遗漏的。

时间复杂度$O(n^3)$。

C++ Code:

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
int n,m,d[202][202],s[202][202],ans[202];
bool has[202];
inline int readint(){
	char c=getchar();
	for(;!isdigit(c);c=getchar());
	int d=0;
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^‘0‘);
	return d;
}
int main(){
	n=readint(),m=readint();
	memset(d,0x3f,sizeof d);
	while(m--){
		int x=readint(),y=readint(),z=readint();
		d[x][y]=d[y][x]=z;
	}
	for(int k=1;k<=n;++k)
	for(int i=1;i<=n;++i)
	if(i!=k)
	for(int j=1;j<=n;++j)
	if(i!=j&&j!=k){
		if(d[i][j]>d[i][k]+d[k][j]){
			d[i][j]=d[i][k]+d[k][j];
			s[i][j]=k;
		}else
		if(d[i][j]==d[i][k]+d[k][j])s[i][j]=-1;
	}
	int cnt=0;
	memset(has,0,sizeof has);
	for(int i=1;i<=n;++i)
	for(int j=1;j<=n;++j)
	if(s[i][j]>0&&!has[s[i][j]]){
		has[s[i][j]]=true;
		ans[++cnt]=s[i][j];
	}
	if(cnt==0)return puts("No important cities."),0;
	std::sort(ans+1,ans+cnt+1);
	for(int i=1;i<cnt;++i)printf("%d ",ans[i]);
	printf("%d\n",ans[cnt]);
	return 0;
}

 

以上是关于[JSOI2007]重要的城市(x)的主要内容,如果未能解决你的问题,请参考以下文章

Floydp1841[JSOI2007]重要的城市

luogu P1841 [JSOI2007]重要的城市 dp+Floyd

luogu P1841 [JSOI2007]重要的城市 dp+Floyd

BZOJ.1029.[JSOI2007]建筑抢修(贪心)

P4049 [JSOI2007]合金

LG2145 「JSOI2007」祖码 区间DP