zoukankan      html  css  js  c++  java
  • 最短路+找规律 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
  • 相关阅读:
    冒泡排序
    三种for循环遍历
    打印一年中的月历
    基于主主复制的mysql双机热备+keepalived实现高可用性
    docker实现apache+php容器和mysql容器独立运行
    XML和JSON
    PHP表单
    【翻译-Docker】Post-installation steps for Linux
    【翻译】docker install
    小计划
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6818765.html
Copyright © 2011-2022 走看看