Codeforces Round #621 (Div. 1 + Div. 2).D. Cow and Fields
第三次写博客,请多指教!
这篇博客是本人为了回顾思路,各位看官爱看不看(手动滑稽)!
http://codeforces.com/contest/1307/problem/D 题目链接
题目大意就是要你从k个特殊点选出两个点连边,问连边之后1到n的最短路距离最大是多少
那么直接说思路,先用bfs找出1号点到所有点的最短距离 再找出n号点到所有点的最短距离
分别存在dis[][0],dis[][1]中。那么有了最短距离。
接下来只需要枚举即可
遍历所有点,当前点 j 到 n 号点的距离就是 dis[i][1];其与比它更靠近1号点的某个点位 i 到1号点的距离 dis[i][0]的距离和 +1 就是当前的最短路;
因为要使最短路最大 所以i要尽可能离1号点远的同时又不能小于dis[j]+1 ;问题来了这个点怎么求呢?
有dis[i][0]+1+dis[j][1]<=dis[j][0]+1+dis[i][1] 即 dis [i][0]-dis[i][n]<dis[j][0]-dis[j][n];
根据这个关系进行排序即可;
上代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define lson l,m,rt<<1 4 #define rson m+1,r,rt<<1|1 5 #define rush ios::sync_with_stdio(false);cin.tie(0); 6 const int inf = 0x3f3f3f3f; 7 const long long linf = 0x3f3f3f3f3f3f3f3f; 8 int dis[200005][2]; 9 int tes[200005]; 10 vector<int>g[200005]; 11 int n,m,k; 12 int check[200005]; 13 struct vt{ 14 int X1;int Xn; 15 }s[200005]; 16 bool cmp(const vt &x,const vt &y) 17 { 18 return x.X1-x.Xn<y.X1-y.Xn; 19 } 20 void bfs(int x,int st) 21 { 22 queue<int>v; 23 v.push(x); 24 for(int i=1;i<=n;i++)check[i]=0; 25 check[x]=1; 26 while(!v.empty()) 27 { 28 int temp=v.front(); 29 v.pop(); 30 for(auto i:g[temp]) 31 { 32 if(!check[i]){ 33 dis[i][st]=dis[temp][st]+1; 34 check[i]=1; 35 v.push(i); 36 } 37 } 38 } 39 } 40 int main() 41 { 42 rush 43 cin>>n>>m>>k; 44 for(int i=0;i<k;i++) 45 { 46 cin>>tes[i]; 47 } 48 for(int i=0;i<m;i++){ 49 int a,b; 50 cin>>a>>b; 51 g[a].push_back(b); 52 g[b].push_back(a); 53 } 54 bfs(1,0); 55 bfs(n,1); 56 for(int i=0;i<k;i++) 57 { 58 s[i].X1=dis[tes[i]][0]; 59 s[i].Xn=dis[tes[i]][1]; 60 } 61 sort(s,s+k,cmp);int tem=0,ans=0; 62 for(int i=0;i<k;i++) 63 { 64 if(i!=0){ 65 ans=max(ans,tem+s[i].Xn+1); 66 } 67 tem=max(tem,s[i].X1); 68 } 69 cout<<min(dis[n][0],ans)<<endl; 70 }
rush!