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\n",ans);
return 0;
}

浙公网安备 33010602011771号