codeforces 621 D Cow and Fields

題目鏈接:D
題意:給定一個點數爲3e5,邊數爲3e5的且保證連通的邊權都爲1的無向圖,給定k個特殊點,(2<=k<=n)(2<=k<=n),定義要計算的路徑長度是從1到n的最短路,現在要求你選擇兩個特殊點之間加一條長度爲1的邊,問你在所有方案中,要計算的路徑長度最大的是多少。

昨晚看這一場很晚了就沒打,但十一點多看了一下該題,口胡了一個做法。

首先可以知道答案一定是小於等於原來不加邊的最短路的。
因爲不管怎麼加邊都不會使得已存在的最短路變長。
兩次bfs預處理出dis1[x],disn[x]dis1[x],disn[x],分別表示從1n1,n出發到xx的最短路長度。
所以其實可以想到一個較爲暴力的做法,任取兩特殊點iji,j,計算:
Max(min(dis1[i]+disn[j]+1,disn[i]+disj[1]+1,dis1[n]))Max(min(dis1[i]+disn[j]+1,disn[i]+disj[1]+1,dis1[n])),就是最終答案。
現在考慮不那麼暴力的做法,枚舉特殊點xx,考慮往哪個特殊點上加邊,假設加到了jj上,那麼dis1[x]+disn[j]+1就可能是新的最短路,其他點都沒有受到影響,那要使得這條最短路儘可能的大,那其實就是找max(disn[j])。但是這裏有一點需要注意,你應該找的是在bfs過程中x延伸出去特殊點中disn最大的一項。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn=2e5+7;
vector<int> G[maxn];

int dis1[maxn],disn[maxn];
queue<int> q;
bool vis[maxn];
void bfs(int st,int dis[]){
    q.push(st);
    memset(vis,0,sizeof(vis));
    dis[st]=0;
    vis[st]=1;
    while(q.size()){
        int u=q.front(); q.pop();
        for(auto v:G[u])
            if(!vis[v]){
                dis[v]=dis[u]+1;
                q.push(v);
                vis[v]=1;
            }
    }
}

int b[maxn];
vector<int> v;//存儲所有從n出發到特殊點的最短路徑;
vector<int> te;
int main(){
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=1,x;i<=k;++i){
        scanf("%d",&x);
        te.push_back(x);
    }
    while(m--){
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    bfs(1,dis1);
    bfs(n,disn);
    int res=0;

    for(auto x:te) v.push_back(disn[x]);
    sort(v.begin(),v.end());
    for(auto x:te){
        vector<int>::iterator it = upper_bound(v.begin(),v.end(),disn[x]);
        --it;
        if(it==v.begin()) continue;
        --it;//將本身x排除在外;
        //cout<<dis1[x]+(*it)+1<<endl;
        res=max(res,min(dis1[n],dis1[x]+(*it)+1));

    }
    if(res==0) res=dis1[n];
    cout<<res<<endl;

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章