Codeforces Round #621 (Div. 1 + Div. 2) D. Cow and Fields 01最短路+贪心

跑一边01最短路,每个点经过的时间戳id记录下来

刚开始因为n号点的时间戳最大,那么直接按id排序,相邻2个特殊点连边,(这样尽可能不优化最短路)记录id[i]-id[i-1]最小的即可,(此时连边缩短的路径最短)

后来wa后才发现,n号点不一定是距离最远的点,那么对于2个特殊点,

1.如果他们都在同一条1-n的最短路径上,那么按上面的方法处理是没错的,

2.如果2个点都不在1-n最短路径,那么最终结果一定是刚开始的最短路ans。

3.如果一个点在1-n的最短路径,另一个点不在或者不在同一条最短路径。连这两个边后距离为id[x]-1+id2[y]-1+1;

id2为从n开始跑01最短路的时间戳。

这种情况也是让x与y的1时间戳id越接近越好,(因为越接近,连接后优化的距离就越小)。

综合1-3  我们按id排序,取max(id[x]-1+id2[y]-1+1).

如果max大于ans说明是第二种情况,直接输出ans即可。

看了其他人的解法发现:

其实不用思考这么多,直接求min(id[x]+id2[y]-1,id[y]+id2[x]-1);就是连x-y边的最短路径

然后求出所有最短路的最大值,再与ans取min即可。

由于id[x]-id2[x]<=id[y]-id2[y]   时(令左边小于右边,移项得到)  min(id[x]+id2[y]-1,id[y]+id2[x]-1)=id[x]+id2[y]-1,

相当于按id[x]-id2[x]排序,然后对于每个x,id[x]固定时,id2[y]取最大即可(y>x)。

一个经典的排序。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//typedef __int128 LL;
//typedef unsigned long long ull;
//#define F first
//#define S second
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
const ld PI=acos(-1);
const ld eps=1e-9;
//unordered_map<int,int>mp;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
//#define a(i,j) a[(i)*(m+2)+(j)]  //m是矩阵的列数
//pop_back()
const int seed=131;
const int M = 2e5+7;

int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
int id[M],vs[M];
int n,m,k,u,v;
struct node
{
	int a,id,id2;
}p[M];
bool cmp(node a,node b)
{
	return a.id<b.id;
}
void bfs()
{
	queue<int>q;
	q.push(1);vs[1]=1;id[1]=1;
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int i=head[u];i;i=ee[i].nxt)
		{
			int v=ee[i].to;
			if(vs[v])continue;
			q.push(v),vs[v]=1,id[v]=id[u]+1;
		}
	}
	int ans=id[n]-id[1];
	for(int i=1;i<=k;i++)p[i].id=id[p[i].a];
	q.push(n);memset(vs,0,sizeof(vs));id[n]=1;vs[n]=1;
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int i=head[u];i;i=ee[i].nxt)
		{
			int v=ee[i].to;
			if(vs[v])continue;
			q.push(v),vs[v]=1,id[v]=id[u]+1;
		}
	}
	for(int i=1;i<=k;i++)p[i].id2=id[p[i].a];
	sort(p+1,p+1+k,cmp);
	int mx=0;
	for(int i=2;i<=k;i++)
		mx=max(mx,p[i-1].id-1+p[i].id2-1+1);
	//cout<<mi<<endl;
//	for(int i=1;i<=n;i++)
//	cout<<i<<" "<<id[i]<<endl;
	cout<<min(mx,ans)<<endl;
}
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	cin>>n>>m>>k;
  	for(int i=1;i<=k;i++)cin>>p[i].a;
  	for(int i=1;i<=m;i++)cin>>u>>v,add(u,v),add(v,u);
	bfs();
	return 0;
}
发布了284 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/bjfu170203101/article/details/104381545