• 最短路+找规律 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest L. Right Build


    题目链接:http://codeforces.com/gym/101149/problem/L

    题目大意:有n个点(其实是n+1个点,因为编号是0~n),m条有向边。起点是0,到a和b两个节点,所经过的最少的节点的数目是多少?(a和b也算,0不算)

    思路:

    真的是想了半天了,不知道怎么做,虽然知道是最短路,还是偏离了方向。最后万不得已的翻了题解。

    题解看的是这个人的:链接

    思路大体就是:

    因为如果要到两个点,路径上的点肯定是有相交点的(因为0是必然要走的)。然后如果两者路径相交,肯定选择共同相交的走。所以说,两条路径的刚开始是必然相交的,到后来才会分开。

    所以我们就只需要求出distance,然后o->c + a->c + b->c的距离就好了

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 2e5 + 5;
    const int inf = 0x3f3f3f3f;
    int n, m, a, b;
    vector<int> G[maxn];
    pair<int, int> edges[maxn];
    struct Point{
        int u, dis;
        bool operator < (const Point &rhs) const{
            return dis > rhs.dis;
        }
    };
    int d1[maxn], d2[maxn], d3[maxn];
    
    void dijstra(int s, int d[]){
        for (int i = 0; i <= n; i++) d[i] = 1000000000;
        d[s] = 0;
        priority_queue<Point> que;
        que.push(Point{s, d[s]});
        while (!que.empty()){
            int u = que.top().u; que.pop();
            for (int i = 0; i < G[u].size(); i++){
                int v = G[u][i];
                if (d[v] > d[u] + 1){
                    d[v] = d[u] + 1;
                    que.push(Point{v, d[v]});
                }
            }
        }
    }
    
    int main(){
        scanf("%d%d%d%d", &n, &m, &a, &b);
        for (int i = 1; i <= m; i++){
            int u, v; scanf("%d%d", &u, &v);
            edges[i] = mk(u, v);
            G[u].pb(v);
        }
        dijstra(0, d1);
        for (int i = 0; i <= n; i++){
            G[i].clear();
        }
        for (int i = 1; i <= m; i++){
            int u = edges[i].se, v = edges[i].fi;
            G[u].pb(v);
        }
        dijstra(a, d2);
        dijstra(b, d3);
        int ans = 1000000000;
        for (int i = 0; i <= n; i++){
            ans = min(ans, d1[i] + d2[i] + d3[i]);
        }
        cout << ans << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    使用正则表达式验证密码长度
    创建字符串
    洛谷P1605 迷宫 深度搜索 模板!
    洛谷P5534 【XR-3】等差数列 耻辱!!!
    搜索字母a或A
    洛谷P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here
    19新生赛 质数中的质数
    洛谷P1055 ISBN号码
    洛谷P 1427 小鱼的数字游戏
    洛谷p1047 校门外的树
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6818765.html
Copyright © 2020-2023  润新知