zoukankan      html  css  js  c++  java
  • Codeforces Round #621 (Div. 1 + Div. 2)D dij(思维)

    题:https://codeforces.com/contest/1307/problem/D

    题意:给定无向图,n为点,m为边。在给个k,为特殊点的数目,题目要求在这些特殊点上连一条边,让新图最短路尽可能大,问新图最短路(1到n)是多少?

    分析:因为题目保证连通且原本的图一定可以从1到n,我们假设原本的图最短路为ans;

       易得虽然要求我们最大化最短路,但是加一条边只可能让答案不变或变小(因为一定要加这条边),不会使最短路变大;

       假设我们在特殊点x和y之间加了边,要是新图的最短路有走这条边,那么新图的最短路长度一定是p[x].t1+p[y].tn+1,p[].t1表示原本图以1为起点的最短路数组,p[].tn则是以n为起点;

       这里有个问题:那么是不是找到最大的t1和最大的tn相加就能得到最短路的?这个结论的错误的,有个简单的反例,假设图为一条链(1为链头,n为链尾),那么最大的t1和tn肯定就是n,长度为2(n-1)+1,但是点1和点n连起来后最短路就变成了1,而不是2(n-1)+1,这样的情况在更大的图中更有体现

       所以我们这里采用min(p[x].t1+p[y].tn+1,p[y].t1+p[x].tn+1),因为最短路,所以是要取其中较小的,化简一下就是p[x].t1-p[x].t2<p[y].t1-p[y].t2,取值小的x就作为1号点,y作为2号点,在代码中就体现为取max前面的t1,和当前的t2相加,取max到答案上;

       处理方法就是将k个点按照这个优先级来排序,那么当前的p[i].tn和i之前的t1组成的长度就是我们要的最短路,然后就贪心地把t1取成 i 之前最大的ti就行

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int INF=0x3f3f3f3f;
    const int MAXN=1000010;
    int t1[MAXN],t2[MAXN];
    struct qnode{ 
        int v;
        int c;
        qnode(int _v=0,int _c=0):v(_v),c(_c){} 
        bool operator <(const qnode &r)const{
         return c>r.c; 
         } 
    }; 
    struct Edge{ 
         int v,cost;
          Edge(int _v=0,int _cost=0):v(_v),cost(_cost){} 
    }; 
    vector<Edge>E[MAXN]; 
    bool vis[MAXN];
    int dist[MAXN],vis1[MAXN],vis2[MAXN],pre[MAXN];
    void Dij(int n,int start){
        memset(vis,false,sizeof(vis)); 
        for(int i=1;i<=n;i++)
            dist[i]=INF;
        priority_queue<qnode>que;
        while(!que.empty())que.pop();
        dist[start]=0; 
        que.push(qnode(start,0));
        qnode tmp; 
            while(!que.empty()){ 
                 tmp=que.top(); 
                  que.pop(); 
                  int u=tmp.v; 
                  if(vis[u])continue;
                   vis[u]=true;
                for(int i=0;i<E[u].size();i++){ 
                     int v=E[tmp.v][i].v; 
                      int cost=E[u][i].cost;
                      if(!vis[v]&&dist[v]>dist[u]+cost){ 
                           dist[v]=dist[u]+cost;
                        que.push(qnode(v,dist[v])); 
                    
                    } 
                } 
            } 
    } 
    void addedge(int u,int v,int w){
        E[u].push_back(Edge(v,w));
    }
    struct node{
        int t1,tn;
    }p[MAXN];
    bool cmp(int x,int y){
        return p[x].t1+p[y].tn<p[x].tn+p[y].t1;
    }
    int a[MAXN];
    int main(){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=k;i++){
            scanf("%d",&a[i]);
        }
        while(m--){
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v,1);
            addedge(v,u,1);
        }
        Dij(n,1);
        int ans=0;
        for(int i=1;i<=n;i++)
            p[i].t1=dist[i];///从1出发的最短路 
    
        Dij(n,n);
        for(int i=1;i<=n;i++)
            p[i].tn=dist[i];///从n出发的最短路 
        sort(a+1,a+1+k,cmp);
        int maxx=p[a[1]].t1;
        for(int i=2;i<=k;i++){
            ans=max(ans,maxx+p[a[i]].tn+1);
            maxx=max(maxx,p[a[i]].t1);
        }
        printf("%d
    ",min(ans,p[n].t1));
        return 0;
    }
    View Code
  • 相关阅读:
    java学习---集合框架
    java学习--java.util包中常用类
    java学习--java.lang包中常用的类
    JAVA学习--OOP
    Python入门-Hello Word
    【洛谷1452】【模板】旋转卡壳
    【洛谷2766】最长不下降子序列问题(网络流)
    【洛谷3355】骑士共存问题(网络流)
    【洛谷1251】餐巾计划问题(费用流)
    【洛谷3358】最长k可重区间集问题(费用流)
  • 原文地址:https://www.cnblogs.com/starve/p/12326068.html
Copyright © 2011-2022 走看看