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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章