Codeforces Round #621 (Div. 1 + Div. 2) D. Cow and Fields 详解

D. Cow and Fields
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Bessie is out grazing on the farm, which consists of n fields connected by m bidirectional roads. She is currently at field 1, and will return to her home at field n at the end of the day.

The Cowfederation of Barns has ordered Farmer John to install one extra bidirectional road. The farm has k special fields and he has decided to install the road between two different special fields. He may add the road between two special fields that already had a road directly connecting them.

After the road is added, Bessie will return home on the shortest path from field 1 to field n. Since Bessie needs more exercise, Farmer John must maximize the length of this shortest path. Help him!

Input
The first line contains integers n, m, and k (2≤n≤2⋅105, n−1≤m≤2⋅105, 2≤k≤n) — the number of fields on the farm, the number of roads, and the number of special fields.

The second line contains k integers a1,a2,…,ak (1≤ai≤n) — the special fields. All ai are distinct.

The i-th of the following m lines contains integers xi and yi (1≤xi,yi≤n, xi≠yi), representing a bidirectional road between fields xi and yi.

It is guaranteed that one can reach any field from every other field. It is also guaranteed that for any pair of fields there is at most one road connecting them.

Output
Output one integer, the maximum possible length of the shortest path from field 1 to n after Farmer John installs one road optimally.

Examples
inputCopy
5 5 3
1 3 5
1 2
2 3
3 4
3 5
2 4
outputCopy
3
inputCopy
5 4 2
2 4
1 2
2 3
3 4
4 5
outputCopy
3

题意:
已知n点的m条双向路可连成无向连通图,再给你k个点,选其二连双向边,求最短路的最大值。

思路:
在原最短路的基础上加边,结果只会小于等于原最短路。
那么我们要做的就是在k个点里面选两个点,k^2枚举肯定不行,任选两个点,xy。
1到n有两种情况: 1->x->y->n 或者 1->y->x->n
写成式子是 : d1[x]+1+dn[y] 和 d1[y]+1+dn[x]
最短路 那么就是两者取min
那么如何确定x和y呢? 假设取 1->x->y->n 这一路线 有:
d1[x]+1+dn[y]< d1[y]+1+dn[x] 相当于 d1[x]-dn[x]<d1[y]-dn[y]
那么我们可知 当我们选取任一点y时,选取的x使得d1[x]最大,那么最短路最大。
所以按 d1[x]-dn[x] 排序,然后取前面的max(d1[i] ) 即可使最短路最大。
当然答案怎么大也得小于等于d1[n] 。

代码:

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define ll long long
//#define ll unsigned long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-6
#define pi acos(-1)
#define myit set<ll>::iterator
#define mysets multiset<ll>
#define myits multiset<ll>::iterator
#define all(x) (x).begin(),(x).end()
#define maxs *s.rbegin()
#define lowbit(x) (x&(-x))
#define ispow(n) (n & (n - 1))
#define mp make_pair
#define pb push_back
using namespace std;
inline ll read(){
   ll s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b);}
using namespace std;
 
const int manx=2e5+5;
const int mamx=4e5+5;
ll head[manx],d[manx][2],pre[manx];
bool vis[manx];
ll n,m,k=0,s,e;
struct node{
    int v,next,w;
}a[mamx];
void add(int u,int v,int w)
{
    a[++k].next=head[u];
    a[k].w=w;
    a[k].v=v;
    head[u]=k;
}
void dij(int x)
{
    for(int i=1;i<=n;i++) vis[i]=0,d[i][x]=1e9;
    d[s][x]=0;
    priority_queue<pair<int,int> >q;
    q.push(make_pair(0,s));
    while(q.size()){
        int u=q.top().second;
        q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=head[u];i;i=a[i].next){
            int v=a[i].v,w=a[i].w;
            if(d[v][x]>d[u][x]+w) d[v][x]=d[u][x]+w,q.push(make_pair(-d[v][x],v));
        }
    }
 
}
int main()
{
    n=read(),m=read();
    ll x=read();
    for(int i=1;i<=x;i++) pre[i]=read();
    for(int i=1;i<=m;i++)
    {
        ll u=read(),v=read(),w=1;
        add(u,v,w);
        add(v,u,w);
    }
    e=n,s=1;
    dij(0);
    s=n,e=1;
    dij(1);
    vector<pair<ll,ll> >p;
    for(int i=1;i<=x;i++){
        p.pb(mp(d[pre[i]][0]-d[pre[i]][1],pre[i]));
    }
    sort(all(p));
    ll ans=0,res=0;
    for(int i=0;i<x;i++){
        if(i) ans=max(ans,res+d[p[i].second][1]+1);
        res=max(res,d[p[i].second][0]);
    }
    cout<<min(d[n][0],ans)<<endl;
    return 0;
}
发布了67 篇原创文章 · 获赞 35 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/JiangHxin/article/details/104377037