Codeforces Round #621 (Div. 1 + Div. 2) Cow and Fields——最短路

差点忘记补题.

这题是一个非常好的结论题:

首先可以确定,加一条边之后,最短路会变小或者不变。

看了网上非常多的对于这个题目的看法,现在终于搞懂原理。

很容易误解的一个点:为什么按照差值排序?差值排序的目的?

很多以为差值排序是为了选择哪几个点排序——错误认识

差值排序只是为了得到 顺序:

加一条边必定会引起一条最短路改变或者不改变。预先处理出 a,b两个数组,a_x代表1~x的最短距离,b_x代表n~x的最短距离,那么如果选择两个点(x,y)的话,新的最短路的权值为:a_x+b_y+1 或者 a_y+b_x+1,我们知道这两个里面只有一条是最短路(其实就是 谁在前面 ,否则的话会多走重复的路)。所以假设 前者为最短路 a_x+b_y+1<a_y+b_x+1  ——— a_x-a_y<b_x-b_y, 那么这个式子也就证明 当x的差值比y的差值小的话,x一定是链接1的那个点(x在y的前面),这样一来我们只需要得到一个后缀y的最大值就可以了。最后与最短路取个min

/*** keep hungry and calm CoolGuang!***/
#include <bits/stdc++.h>
#include<stdio.h>
#include<vector>
#include<algorithm>
#pragma GCC optimize(2)
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pp;
const ll INF=1e18;
const ll maxn=1e6+5;
const int mod=1e9+7;
inline bool read(ll &num)
{char in;bool IsN=false;in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
vector<int>v[maxn];
ll num[maxn];
ll a[maxn],b[maxn];
int vis[maxn];
struct node{
    ll a,b;
    bool friend operator<(node a,node b){
        return a.a-a.b<b.a-b.b;
    }
}save[maxn];
void bfs(int s,ll *p){
    for(int i=1;i<=n;i++) vis[i]=0;
    queue<int>q;
    q.push(s);vis[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        int sz=v[u].size();
        for(int k=0;k<sz;k++){
            int e=v[u][k];
            if(!vis[e]){
                p[e]=p[u]+1;
                vis[e]=1;
                q.push(e);
            }
        }
    }
}
int main()
{
    scanf("%lld%lld%lld",&n,&m,&p);
    for(int i=1;i<=p;i++) scanf("%lld",&num[i]);
    for(int i=1;i<=m;i++){
        int x,y;scanf("%d%d",&x,&y);
        v[x].push_back(y);
        v[y].push_back(x);
    }
    bfs(1,a);bfs(n,b);
    for(int i=1;i<=p;i++){
        save[i].a=a[num[i]];
        save[i].b=b[num[i]];
    }
    sort(save+1,save+1+p);
    ll maxl=save[p].b;
    ll ans=-INF;
    for(int i=p-1;i>=1;i--){
        ans=max(ans,save[i].a+maxl+1);
        maxl=max(maxl,save[i].b);
    }
    printf("%lld\n",min(ans,a[n]));
    return 0;
}
发布了157 篇原创文章 · 获赞 146 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/104452393