D. Cow and Fields
题意
有n个点 m条边 k个特殊点
现在给出k个特殊点下标
和已有的m条边
问在k个特殊点中选两个点建一条边
使得1到n的最短路最大
题解
对于两个特殊点 x y
如果在这两点之间建立一条边那么经过这两点的最短路长为
min(1->x+y->n , 1->y+x->n)中产生
假设(1->x+y->n) < (1->y+x->n) 为了使最短路更长
我们选择更大的 (1->x+y->n) 同时又要满足(1->x+y->n) < (1->y+x->n)
所以将(1->x+y->n) < (1->y+x->n)转化为(1->x - x->n) <(1->y- y->n)
此时选择两个特殊点 x y 时只要满足 (1->x - x->n) <(1->y- y->n)
那么 (1->x+y->n) 将有可能成为最长的最短路
所以根据(1->x - x->n) <(1->y- y->n) 将特殊点排序
现在要想 (1->x+y->n) 尽量大 在满足(1->x - x->n) <(1->y- y->n) 的前提条件下 更新排序后前i个特殊点1-> i的最大值 maxp + i->y的距离+1 就是加边后最长最短路
注意最长的最短路不会比原有1->n的路径长
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| # include<bits/stdc++.h>
using namespace std; typedef long long ll;
# define endl '\n'
const int maxn=(int)2e5+10; int special[(int)2e5+4]; vector<int>point[(int)2e5+5]; int dis[3][(int)2e5+4]; void bfs(int pos,int type){ dis[type][pos]=0; queue<int>q;q.push(pos); while(!q.empty()){ int now=q.front();q.pop(); for(auto i:point[now]){ if(dis[type][i]==maxn){ dis[type][i]=dis[type][now]+1; q.push(i); } } } } int main(){ int n,m,k;cin>>n>>m>>k; for(int i=0;i<=n;i++)dis[1][i]=maxn,dis[0][i]=maxn; for(int i=0;i<k;i++)cin>>special[i]; for(int i=0;i<m;i++){ int x,y;cin>>x>>y; point[x].push_back(y); point[y].push_back(x); } bfs(1,0);bfs(n,1); vector<pair<int,int> >sp; for(int i=0;i<k;i++){ sp.push_back({dis[0][special[i]]-dis[1][special[i]],special[i]}); } sort(sp.begin(),sp.end()); int ans=0,maxp=-maxn; for(auto i:sp){ int pos=i.second; ans=max(ans,maxp+dis[1][pos]); maxp=max(maxp,dis[0][pos]); } cout<<min(ans+1,dis[0][n])<<endl; }
|