[Luogu P1841] [JSOI2007]重要的城市

洛谷传送门

题目描述

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

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

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

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

输入输出格式

输入格式:

第一行两个整数 N , M N,M N,M, N N N为城市数, M M M为道路数

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

输出格式:

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

输入输出样例

输入样例#1:
4 4
1 2 1
2 3 1
4 1 2
4 3 2
输出样例#1:
2

说明

30 % 30\% 30%的数据: N ≤ 20 N\le 20 N20

60 % 60\% 60%的数据: N ≤ 100 N\le 100 N100

100 % 100\% 100%的数据: N ≤ 200 , M ≤ N × ( N − 1 ) 2 , 0 &lt; c ≤ 10000 N\le 200,M\le \frac{N\times (N-1)}{2},0&lt;c\le 10000 N200,M2N×(N1),0<c10000 c c c即路的长度。

保证不出现重边和自环

如果没有点的话需要输出一行

“No important cities.”

解题分析

f l o y d floyd floyd更新的时候如果两次更新到同路径并且长度相同, 就说明当前路径没有重要城市。 最后用个桶记录一下就好。

代码如下:

#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 205
template <class T>
IN void in(T &x)
{
    x = 0; R char c = gc;
    for (; !isdigit(c); c = gc);
    for (;  isdigit(c); c = gc)
    x = (x << 1) + (x << 3) + c - 48;
}
int dis[MX][MX], imp[MX][MX], buc[MX];
int dot, line;

int main(void)
{
    int a, b, c, out = 0;
    in(dot), in(line);
    std::memset(dis, 63, sizeof(dis));
    std::memset(imp, -1, sizeof(imp));
    for (R int i = 1; i <= dot; ++i) dis[i][i] = 0;
    for (R int i = 1; i <= line; ++i)
    in(a), in(b), in(c), dis[a][b] = dis[b][a] = std::min(c, dis[a][b]);
    for (R int k = 1; k <= dot; ++k)
    for (R int i = 1; i <= dot; ++i)
    if(i ^ k) for (R int j = 1; j <= dot; ++j)
    {
        if(i ^ j && j ^ k)
        if(dis[i][j] > dis[i][k] + dis[k][j]) dis[i][j] = dis[i][k] + dis[k][j], imp[i][j] = k;
        else if(dis[i][j] == dis[i][k] + dis[k][j]) imp[i][j] = 0;
    }
    for (R int i = 1; i <= dot; ++i)
    for (R int j = 1; j <= dot; ++j) buc[imp[i][j]]++;
    for (R int i = 1; i <= dot; ++i) if(buc[i]) printf("%d ", i), out = true;
    if(!out) puts("No important cities.");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值