• CodeForces1307D 最短路


    题意

    Cgg正在农场放牧,该农场由n个由m条双向道路连接的田地组成。目前Cgg在1号田地,并将在一天结束时到达位于第n号田地的家。
    出于对农场发展的考虑,小黄毛牛头人协会命令Cgg铺设一条额外的双向道路。 其中该农场有k个特殊田地,Cgg决定在两个不同的特殊田地之间安装道路。
    注意,Cgg可以在已经连接两个特殊字段之间添加道路。(即允许创建重边)
    添加道路后,Cgg将沿着从1号田地到n号田地的最短路径返回家中。 由于Cgg的牛需要更多的运动,因此Cgg必须最大限度地增加这条最短路径的长度。 帮帮他!

    解法

    容易想到求出所有的special点到1和N的最短路dis1和dis2,然后从中选出两个点i,j加上边之后,就会形成一条新的“可能的最短路”长度DIS = min(dis1[i],dis2[j]) + 1 + min(dis2[i],dis2[j])
    题目转化为找出其中最大的点对使得DIS最大,观察式子发现可以将dis1从小到大排序,然后求出一个dis2的后缀最大值,就可以O(n)算出来

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define fi first
    #define se second
    #define PII pair<int,int>
    #define PLL pair<long long,long long>
    #define mp make_pair
    const int maxn = 2e5 + 10;
    const int maxm = 31630;
    int N,M,K;
    
    struct Edge{
        int to,next;
    }edge[maxn * 2];
    int head[maxn],tot;
    void init() {
        for(int i = 0 ; i <= N ; i ++) head[i] = -1;
        tot = 0;
    }
    void add(int u,int v){
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    const int INF = 0x3f3f3f3f;
    struct SpNode {
        int id;
        int dis1,dis2;
        SpNode(){}
        SpNode(int id, int dis1, int dis2):id(id),dis1(dis1),dis2(dis2){}
    };
    vector<SpNode> sp;
    int dis[maxn];
    struct node {
        int pos,val;
        node(int pos,int val):pos(pos),val(val){}
        friend bool operator < (node a,node b) {
            return a.val > b.val;
        }
    };
    void Dijkstra(int s) {
        for(int i = 0; i <= N ; i ++) dis[i] = INF;
        dis[s] = 0;
        priority_queue<node>Q;
        Q.push(node(s,0));
        while(!Q.empty()) {
            node u = Q.top(); Q.pop();
            if(u.val > dis[u.pos]) continue;
            for(int i = head[u.pos]; ~i; i = edge[i].next) {
                int v = edge[i].to;
                if(dis[v] > 1 + u.val) {
                    dis[v] = 1 + u.val;
                    Q.push(node(v,dis[v]));
                }
            }
        }
    }
    bool cmp(SpNode a,SpNode b){
        return a.dis1 < b.dis1;
    }
    int preMax[maxn];
    int main(){
        scanf("%d%d%d",&N,&M,&K); init();
        for(int i = 1; i <= K; i ++) {
            int x; scanf("%d",&x);
            sp.push_back(SpNode(x,0,0));
        } 
        for(int i = 1; i <= M ; i ++) {
            int u,v; scanf("%d%d",&u,&v);
            add(u,v), add(v,u);
        }
        Dijkstra(1);
        for(int i = 0 ; i < sp.size(); i ++) {
            sp[i].dis1 = dis[sp[i].id];
        }
        Dijkstra(N);
        int ans = dis[1];
        for(int i = 0 ; i < sp.size(); i ++) {
            sp[i].dis2 = dis[sp[i].id];
        }
        sort(sp.begin(),sp.end(),cmp);
        int tmp = 0;
        for(int j = sp.size() - 1; j >= 0; j--) {
            preMax[j] = max(preMax[j + 1], sp[j].dis2);
        }
        for(int i = 0 ; i < sp.size() - 1; i ++) {
            tmp = max(tmp,sp[i].dis1 + min(sp[i].dis2, preMax[i + 1]) + 1);
        }
        printf("%d", min(ans,tmp));
        return 0;
    }
    
    
    
  • 相关阅读:
    c如何弹出保存路径/保存文件对话框
    c++ 读写txt方法
    windows获取环境变量
    Block UI 获取treelist column值
    MFC中如何弹出选择文件/文件夹对话框(C++)
    What can change the CID of a NX license server?
    spring之AOP
    spring注解开发
    spring配置Bean
    spring之IOC和DI实现
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/13762160.html
Copyright © 2020-2023  润新知