Codeforces Roun d #621 (Div. 1 + Div. 2) D. Cow and Fields 最短路+贪心 图上特殊点加边使最短路最大

题目链接:https://codeforces.ml/contest/1307/problem/D
题目大意:Codeforces Roun d #621 (Div. 1 + Div. 2) D. Cow and Fields 最短路+贪心 图上特殊点加边使最短路最大_第1张图片
有一个无向图n个点m条边,其中有k个特殊点。现在让你在两个特殊点之间连一条边。让1到n的最短路最大, 并且输出这个最短路的大小。

d i s 1 [ i ] : 1 到 i 的 最 短 距 离 d i s 2 [ i ] : n 到 i 的 最 短 距 离 如 果 我 们 在 i 和 j 连 边 最 短 路 可 能 变 成 : m i n ( d i s 1 [ i ] + d i s 2 [ j ] + 1 , d i s 2 [ i ] + d i s 1 [ j ] + 1 ) 这 里 对 于 一 个 点 i 它 和 谁 连 并 不 能 贪 心 。 如 果 规 定 : d i s 2 [ i ] > = d i s 2 [ j ] 那 么 i 和 j 连 边 最 短 路 只 可 能 变 成 d i s 1 [ i ] + d i s 2 [ j ] + 1 。 或 者 d i s 1 [ n ] 我 们 希 望 最 大 化 : d i s 1 [ i ] + d i s 2 [ j ] + 1 。 对 于 一 个 i 点 我 们 这 要 找 到 d i s 2 [ i ] > = d i s 2 [ j ] 并 且 d i s 2 [ j ] 最 大 的 j 点 。 把 所 有 特 殊 点 的 d i s 2 [ ] 加 入 容 器 二 分 就 可 以 了 。 \begin{array}{l} dis1[i]:1到i的最短距离 \\ dis2[i]:n到i的最短距离 \\ 如果我们在i和j连边最短路可能变成:min(dis1[i]+dis2[j]+1, dis2[i]+dis1[j]+1) \\ 这里对于一个点i它和谁连并不能贪心。\\ 如果规定:dis2[i]>=dis2[j]那么i和j连边最短路只可能变成dis1[i]+dis2[j]+1。或者dis1[n]\\ 我们希望最大化:dis1[i]+dis2[j]+1。对于一个i点我们这要找到dis2[i]>=dis2[j]并且dis2[j]最大的j点。\\ 把所有特殊点的dis2[]加入容器二分就可以了。 \end{array} dis1[i]:1idis2[i]:niijmin(dis1[i]+dis2[j]+1,dis2[i]+dis1[j]+1)idis2[i]>=dis2[j]ijdis1[i]+dis2[j]+1dis1[n]dis1[i]+dis2[j]+1idis2[i]>=dis2[j]dis2[j]jdis2[]

#include
#define LL long long
using namespace std;
const int maxn=2e5+5;

vector< pair<int ,int > > e[maxn];
vector<int> v, d;
int n, m;
int dis1[maxn], dis2[maxn];   //dis当前的最短路
int vis[maxn];   //是否已经求出最短路
priority_queue<pair<int, int> > q;
void dijkstra(int s, int dis[], int vis[]){
    dis[s]=0;
    q.push(make_pair(-dis[s], s));
    while(!q.empty()){
        int now=q.top().second;
        q.pop();
        if(vis[now]){
            continue;
        }
        vis[now]=1;
        for(int i=0;i<e[now].size();i++){
            int v=e[now][i].first;
            if(!vis[v]&&dis[v]>dis[now]+e[now][i].second){
                dis[v]=dis[now]+e[now][i].second;
                q.push(make_pair(-dis[v], v));
            }
        }
    }
}

int main(){

    int n, m, k, x, y;scanf("%d%d%d", &n, &m, &k);
    for(int i=1; i<=k; i++){
        scanf("%d", &x);
        v.push_back(x);
    }
    for(int i=1; i<=m; i++){
        scanf("%d%d", &x, &y);
        e[x].push_back({y, 1});
        e[y].push_back({x, 1});
    }
    memset(vis, 0, sizeof(vis));
    memset(dis1, 7, sizeof(dis1));
    dijkstra(1, dis1, vis);

    memset(vis, 0, sizeof(vis));
    memset(dis2, 7, sizeof(dis2));
    dijkstra(n, dis2, vis);
    for(int i=0; i<v.size(); i++){
        d.push_back(dis2[v[i]]);
    }
    sort(d.begin(), d.end());
    int ans=0;
    for(int i=0; i<v.size(); i++){
        vector<int>::iterator p=upper_bound(d.begin(), d.end(), dis2[v[i]]);
        p--;
        if(p==d.begin()){
            continue;
        }
        p--;
        ans=max(dis1[v[i]]+(*p)+1, ans);
    }
    printf("%d\n", min(ans, dis1[n]));

    return 0;
}

你可能感兴趣的:(最短路)