P1841 [JSOI2007]重要的城市 最短路

  

同样的情况也出现在城市间的交通中。某些城市如果出了问题,可能会引起其他很多城市的交通不便。另一些城市则影响不到别的城市的交通。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

如果去掉一个点 存在其他任意两个点的距离变大了 那么说明这是一个重要点 输出所有的重要点

用floyed非常巧妙
#include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int INF=2e6;
    int e[205][205],city[205][205],m,n;
    bool ans[205],cs;
    int main()
    {
        cin>>n>>m;    
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j)
                    e[i][j]=INF;
        for(int i=1,x,y,u;i<=m;i++)
        {
            cin>>x>>y>>u;
            e[x][y]=e[y][x]=u;
        }
        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(e[i][j]>e[i][k]+e[k][j])
                            {
                                e[i][j]=e[i][k]+e[k][j];
                                city[i][j]=k;
                            }
                            else if(e[i][j]==e[i][k]+e[k][j])
                                city[i][j]=-1;
                        }
        for(int i=1;i<=n;i++) 
            for(int j=1;j<=n;j++)
                if(city[i][j]!=-1)
                    ans[city[i][j]]=true;    
        for(int i=1;i<=n;i++)
            if(ans[i])
                cout<<i<<' ',cs=true;
        if(!cs)
            cout<<"No important cities.";
        return 0;
    }
View Code

还有一种用spfa枚举起点的方法:

一个城市x重要,当且仅当去掉它之后可以让s->t的最短路变化(s != t != x)。因为本题的n很小,我们可以枚举n作为s。

当确定s之后,以s为起点跑一次最短路,然后把所有在最短路上的边加入一个新图中。具体做法是:对于一条边,如果它起点处的最短路加上边权等于终点处的最短路,那么就把它加入新图中。

这个新图有一个很好的性质:它是一个DAG。原因很简单,最短路上没环= =。注意到这个最短路DAG记录了s为起点到所有点的最短路。

枚举1~n的每个点。如果存在边x->y,并且y的入度为1,那么删掉x之后y的入度会变成0,显然无法从s到达,即删掉x之后破坏了一些点的最短路。x就是一个关键点。(总而言之  找出所有的最短路  如果入度为1  那么from点就是重要城市)

#include <bits/stdc++.h>
using namespace std;

inline int rd() {
    int a = 1, b = 0; char c = getchar();
    while (!isdigit(c)) a = c == '-' ? 0 : 1, c = getchar();
    while (isdigit(c)) b = b * 10 + c - '0', c = getchar();
    return a ? b : -b;
}

const int N = 500, M = N * N;
struct Graph {
    int from, to, nxt, c;
} g[M * 2];
int head[N], tot;

void addedge(int x, int y, int c) {
    g[++tot].to = y, g[tot].from = x, g[tot].c = c,
    g[tot].nxt = head[x], head[x] = tot;
}

int n, m;

priority_queue<pair<int, int> > que;
int dis[N], in[N];
bool vis[N], important[N], mark[M];

void solve(int s) {
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    dis[s] = 0;
    que.push(make_pair(0, s));
    while (!que.empty()) {
        int x = que.top().second;
        que.pop();
        if (!vis[x]) {
            vis[x] = true;
            for (int i = head[x]; i; i = g[i].nxt) {
                int y = g[i].to;
                if (dis[y] > dis[x] + g[i].c) {
                    dis[y] = dis[x] + g[i].c;
                    que.push(make_pair(-dis[y], y));
                }
            }
        }
    }

    memset(mark, 0, sizeof(mark));
    memset(in, 0, sizeof(in));
    for (int i = 1; i <= tot; ++i) {
        if (dis[g[i].from] + g[i].c == dis[g[i].to]) {
            mark[i] = true;
            printf("from=%d v=%d to=%d\n",g[i].from,g[i].c,g[i].to);
            ++in[g[i].to];
        }
    }

    for (int i = 1; i <= tot; ++i)
        if (mark[i] && in[g[i].to] == 1 && g[i].from != s)
            important[g[i].from] = true;
}

int main() {
    n = rd(), m = rd();
    for (int i = 1; i <= m; ++i) {
        int x = rd(), y = rd(), c = rd();
        addedge(x, y, c), addedge(y, x, c);
    }

        solve(1);
    bool ok = false;
    for (int i = 1; i <= n; ++i)
        if (important[i]) {
            cout << i << " ";
            ok = true;
        }
    if (!ok) cout << "No important cities.";
    cout << endl;
    return 0;
}
View Code





猜你喜欢

转载自www.cnblogs.com/bxd123/p/10963279.html