惨痛教训,这种排序在01背包里也有类似的题目,为啥比赛会想错呢
https://blog.csdn.net/the_love_story/article/details/52179575
/* 每个点i:有两个特征值a[i],b[i] 求两个点i,j,使min(a[i]+b[j],a[j]+b[i])最大 经典的排序问题:就是按 a[i]-b[i]进行排序,这样排序出来后可以确定: 对于所有i<j 都有a[i]-b[i]<a[j]-b[j] => a[i]+b[j]<a[j]+b[i] => 对于所有i<j 其 min(a[i]+b[j],a[j]+b[i]) 的结果都是 a[i]+b[j] => 对于每个a[i],我们去找max(b[j]),j>i即可 */ #include<bits/stdc++.h> using namespace std; #define N 200005 vector<int>G[N]; int n,m,k; int aa[N],a[N],b[N],f[N]; void bfs(int s,int *dis){ queue<int>q;q.push(s); dis[s]=0; while(q.size()){ int u=q.front();q.pop(); for(auto v:G[u]){ if(dis[v] || v==s)continue; dis[v]=dis[u]+1; q.push(v); } } } struct Node{ int a,b,id; }p[N]; int cmp(Node a,Node b){return a.a-a.b<b.a-b.b;} int suf[N]; int main(){ cin>>n>>m>>k; for(int i=1;i<=k;i++)cin>>aa[i],f[aa[i]]=1; int flag=0; for(int i=1;i<=m;i++){ int u,v; cin>>u>>v; G[u].push_back(v); G[v].push_back(u); if(f[u] && f[v])flag=1; } bfs(1,a); bfs(n,b); if(flag){cout<<a[n]<<' ';return 0;} int tot=0; for(int i=1;i<=n;i++)if(f[i]){ ++tot; p[tot].a=a[i]; p[tot].b=b[i]; p[tot].id=i; } sort(p+1,p+1+k,cmp); suf[k]=p[k].b; for(int i=k-1;i>=1;i--) suf[i]=max(suf[i+1],p[i].b); int Max=0; for(int i=1;i<=k-1;i++) Max=max(Max,suf[i+1]+p[i].a); cout<<min(Max+1,a[n])<<' '; }