codeforces#1307D. Cow and Fields(加一条边,最短路径最大)

题目链接:

https://codeforces.com/contest/1307/problem/D

题意:

 在图中添加一条边,连接两个不同的特殊点,使得最短路径最大

分析:

假设连接$v$和$u$,最短路径有三种情况,第一,不走添加的边的最短路径,第二,$1->v->u->n$,第三,$1->u->v->n$

定义$dis1[]$数组为$1$到所有点的最短路径,$dis2[]$数组为$n$到所有点的最短路径

假设$dis1[v]+dis2[u]>=dis1[u]+dis2[v]$,那么$dis1[v]-dis2[v]>=dis1[u]-dis1[u]$,按照差值从小到大排序

如果$u$的位置小于$v$,那么必然满足上式,之后只需要保存$dis2$的前缀最大值即可

 AC代码:

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> PII;

const int maxn=2e5+7;
const int INF=1e9+10;

int dis1[maxn],dis2[maxn],n,m,k,spe[maxn];
VI ve[maxn];
struct Node{
    int a,b;
    bool operator < (const Node other)const{
        return a-b>other.a-other.b;
    }
}node[maxn];
void bfs(int x,int dis[]){
    rep(i,1,n)dis[i]=-1;
    queue<int>que;
    que.push(x);
    dis[x]=0;

    while(SZ(que)){
        int now=que.front();
        que.pop();
        for(auto i:ve[now]){
            if(dis[i]==-1){
                dis[i]=dis[now]+1;
                que.push(i);
            }
        }
    }
}
int main()
{
    scanf("%d %d %d",&n,&m,&k);
    rep(i,1,k){
        scanf("%d",&spe[i]);
    }
    rep(i,1,m){
        int a,b;
        scanf("%d %d",&a,&b);
        ve[a].pb(b);
        ve[b].pb(a);
    }
    bfs(1,dis1);
    bfs(n,dis2);
    rep(i,1,k){
        int w=spe[i];
        node[i]={dis1[w],dis2[w]};
    }
    sort(node+1,node+1+k);
    int ans=-1,maxx=node[1].b;
    rep(i,2,k){
        ans=max(min(dis1[n],node[i].a+maxx+1),ans);
        maxx=max(maxx,node[i].b);
    }
    printf("%d
",ans);
    return 0;
}

  

  

原文地址:https://www.cnblogs.com/carcar/p/12403186.html