LUOGU 1841: [JSOI2007]重要的城市 floyed

title

LUOGU 1841

简化题意:

如果一个城市 \(c\) 在城市 \(a\)\(b(a≠b≠c)\) 的最短路中,并且去掉 \(c\) 最短路就会变短,那么称 \(c\) 为重要的城市。现在要你按次序输出所有重要的城市。如果没有,输出 No important cities.

analysis

\(n\) 非常小,考虑用 \(floyed\) ,时间复杂度 \(O(n^3)\) 可以承受。

转移时记录两点间的重要的城市。

如果两点的距离已经出现过(即出现与原来结果相等的情况),则应删去重要的城市。

最后枚举两个点,把他们的重要的城市去重后记录,排序输出即可,最终时间复杂度为 \(O(n^3)\)

code

#include<bits/stdc++.h>

const int maxn=211;

namespace IO
{
    char buf[1<<15],*fs,*ft;
    inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
    template<typename T>inline void read(T &x)
    {
        x=0;
        T f=1, ch=getchar();
        while (!isdigit(ch) && ch^'-') ch=getchar();
        if (ch=='-') f=-1, ch=getchar();
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
        x*=f;
    }

    char Out[1<<24],*fe=Out;
    inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
    template<typename T>inline void write(T x,char str)
    {
        if (!x) *fe++=48;
        if (x<0) *fe++='-', x=-x;
        T num=0, ch[20];
        while (x) ch[++num]=x%10+48, x/=10;
        while (num) *fe++=ch[num--];
        *fe++=str;
    }
}

using IO::read;
using IO::write;

template<typename T>inline bool chkMin(T &a,const T &b) { return a>b ? (a=b, true) : false; }
template<typename T>inline bool chkMax(T &a,const T &b) { return a<b ? (a=b, true) : false; }
template<typename T>inline T min(T &a,T &b) { return a<b ? a : b; }
template<typename T>inline T max(T &a,T &b) { return a>b ? a : b; }

int d[maxn][maxn],s[maxn][maxn],a[maxn];
bool vis[maxn];
int main()
{
    int n,m;read(n);read(m);
    memset(d,0x3f,sizeof(d));
    for (int i=1,x,y,z; i<=m; ++i) read(x),read(y),read(z),d[x][y]=d[y][x]=min(d[x][y],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 (chkMin(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(vis,0,sizeof(vis));
    for (int i=1; i<=n; ++i)
        for (int j=1; j<=n; ++j)
            if (!vis[s[i][j]] && s[i][j]>0) vis[s[i][j]]=1,a[++cnt]=s[i][j];
    if (!cnt)  return puts("No important cities."),0;
    std::sort(a+1,a+cnt+1);
    for (int i=1; i<=cnt; ++i) write(a[i],i==cnt ? '\n' : ' ');
    IO::flush();
    return 0;
}

转载于:https://www.cnblogs.com/G-hsm/p/11412434.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值