codevs 3971 航班

题目描述 Description

B 国有N 座城市,其中1 号是这座国家的首都。 

N 座城市之间有M 趟双向航班。i 号点的转机次数定义为:从1 号点到i ,最少需要转机几 次。如果1 根本无法到达i ,那么i 点的转机次数是无穷大。 

由于天气原因,有些航班会被取消。 

一趟航班的取消是可容忍的,仅当这趟航班取消之后,2..N 每个点的转机次数不变或者只 增加了1。 

现在kAc 想知道,哪些航班的取消是可容忍的? 

如果这样的航班不存在,输出一行 “hehe”(不含引号) 

输入描述 Input Description

第一行两个正整数N, M 

接下来M 行每行两个正整数a, b。表示当前这趟航班的两端是a,b 两座城市 ,保证a 不等于b ,且同一对a, b 只会出现一次。 

输出描述 Output Description

若干整数,从小到大排序,表示所有的可容忍取消的航班序号。 

样例输入 Sample Input

5 6 

1 2 

1 3 

1 4 

3 4 

2 5 

3 5 

样例输出 Sample Output

数据范围及提示 Data Size & Hint

如果1、2 两座城市间的航班被取消,2 号城市到首都原本需要0 次转机(有直达飞机) ,现 

在需要先到5 ,再到3 ,再到1 ,转机2 次。这是不可忍受的。 

对于40% :N, M<=500 

对于70% :N<=500 M <= 50000 

对于100% :N, M<=200000 

保证初始给定图中所有点的转机次数不是无穷大。 

这其实应该叫次短路,每次改一个点

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;

#define fr(x, E) for (__typeof(E.begin()) x = E.begin(); x != E.end(); x++)
//first ,second,指的是vector中定义的第几个元素 
#define FR first  
#define SC second
#define MP make_pair
#define PB push_back
#define PII pair<int, int>
#define LL long long
#define ALL(x) x.begin(), x.end()
#define SZ(x) ((int)(x).size())
const int MAXN = 1000001;
vector<PII> e[MAXN];//存储边,和第航线序号 
int n, m;
int from[MAXN], vis[MAXN], dis[MAXN];
bool isok[MAXN];
int main()
{
    freopen("flight2.in", "r", stdin); freopen("flight.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++){
        int a, b;
        scanf("%d%d", &a, &b);
        e[a].PB(MP(b, i)); e[b].PB(MP(a, i));
    }
    static queue<int> Q;//宽搜各个顶点到首都的转机次数。 
    Q.push(1); vis[1] = true;//首都1入队列; 
    while(SZ(Q)){//队列非空 
        int x = Q.front(); Q.pop();
        fr(it, e[x])//和队首顶点关联的每个顶点 
            if (!vis[it->FR]){//如果没入队列则入队列 
                vis[it->FR] = true;
                dis[it->FR] = dis[x] + 1;
                from[it->FR] = it->SC;//记录最短路径航线 
                Q.push(it->FR);
        }
    }
    bool ok = true;
    for (int i = 2; i <= n; i++){
        bool nok = true;    //假设对应最短路不可以替换 
        fr(it, e[i])//遍历顶点i的每个关联顶点 ,
    
         //如果存在不在最短路径上,而且距离不超过当前距离的代替顶点 , 
            if (it->SC != from[i] && dis[it->FR] <= dis[i])
               nok = false;//那么,此顶点对应的最短路径这条航线是可以替换的。
        isok[from[i]] = nok;
    }
    bool ex = false;
    for (int i = 1; i <= m; i++) if (!isok[i]){
        printf("%d
", i); ex = true;
    }
    if (!ex) puts("hehe");
}
原文地址:https://www.cnblogs.com/hyfer/p/5811821.html