Cow and Fields CodeForces - 1307D(spfa+思维)

Bessie is out grazing on the farm, which consists of n fields connected by m bidirectional roads. She is currently at field 1, and will return to her home at field n at the end of the day.

The Cowfederation of Barns has ordered Farmer John to install one extra bidirectional road. The farm has k special fields and he has decided to install the road between two different special fields. He may add the road between two special fields that already had a road directly connecting them.

After the road is added, Bessie will return home on the shortest path from field 1 to field n. Since Bessie needs more exercise, Farmer John must maximize the length of this shortest path. Help him!

Input
The first line contains integers n, m, and k (2≤n≤2⋅105, n−1≤m≤2⋅105, 2≤k≤n) — the number of fields on the farm, the number of roads, and the number of special fields.

The second line contains k integers a1,a2,…,ak (1≤ai≤n) — the special fields. All ai are distinct.

The i-th of the following m lines contains integers xi and yi (1≤xi,yi≤n, xi≠yi), representing a bidirectional road between fields xi and yi.

It is guaranteed that one can reach any field from every other field. It is also guaranteed that for any pair of fields there is at most one road connecting them.

Output
Output one integer, the maximum possible length of the shortest path from field 1 to n after Farmer John installs one road optimally.

Examples
Input
5 5 3
1 3 5
1 2
2 3
3 4
3 5
2 4
Output
3
Input
5 4 2
2 4
1 2
2 3
3 4
4 5
Output
3
Note
The graph for the first example is shown below. The special fields are denoted by red. It is optimal for Farmer John to add a road between fields 3 and 5, and the resulting shortest path from 1 to 5 is length 3.
Cow and Fields CodeForces - 1307D(spfa+思维)_第1张图片

The graph for the second example is shown below. Farmer John must add a road between fields 2 and 4, and the resulting shortest path from 1 to 5 is length 3.
Cow and Fields CodeForces - 1307D(spfa+思维)_第2张图片
题意:给定一个n个点m条边的图,这n个点有k个特殊的点,可以在这k个点中找两个点连一条双向虚边。问从1到n的最短路最大是多少。每条边的距离是1。
思路:现在有两个点 i 和 j ,如果其建边的话,最短路可能是 1 -> i -> j -> n 或者 1 -> j -> i -> n。这样我们就很容易想到跑两边最短路分别求出1到所有点的最短路和n到所有点的最短路。这样代表的距离也就是 dis[ i ][ 0 ] + dis[ j ][ 1 ] + 1 和 dis[ i ][ 1 ] + dis[ j ][ 0 ] + 1 了。我们要取最小的,因此 dis[ i ][ 0 ] + dis[ j ][ 1 ] + 1 < dis[ i ][ 1 ] + dis[ j ][ 0 ] + 1 时,才符合最短路的条件。移项后变为dis[ i ][ 0 ] - dis[ i ][ 1 ] < dis[ j ][ 0 ] - dis[ j ][ 1 ]。因此我们按照这个条件由小到大排序后,O(n)枚举一遍位于后面的点 j ,然后找到点 j 前面的 dis[ i ][ 0 ] 的最大值,这样可以保证相加之和是最大的。最大就是之前的最短路了。最后比较一下就可以了。
代码如下:

#include
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;

const int maxx=2e5+100;
struct edge{
	int to;
	int next;
}e[maxx<<1];
struct node{
	int s1,s2,st;
	bool operator<(const node &a)const{
		return st<a.st;
	}
}p[maxx];
int head[maxx<<1],dis[2][maxx],vec[maxx],vis[maxx];
int n,m,k,tot=0;

inline void add(int u,int v)
{
	e[tot].to=v,e[tot].next=head[u],head[u]=tot++;
}
inline void spfa(int c,int s,int ee)
{
	memset(vis,0,sizeof(vis));
	dis[c][s]=0;
	vis[s]=1;
	queue<int> q;
	q.push(s);
	while(q.size())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i!=-1;i=e[i].next)
		{
			int to=e[i].to;
			if(dis[c][to]>dis[c][u]+1)
			{
				dis[c][to]=dis[c][u]+1;
				if(vis[to]==0)
				{
					vis[to]=1;
					q.push(to);
				}
			}
		}
	}
}
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	memset(head,-1,sizeof(head));
	memset(dis,inf,sizeof(dis));
	for(int i=1;i<=k;i++) scanf("%d",&vec[i]);
	int x,y;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	spfa(0,1,n);
	spfa(1,n,1);
	for(int i=1;i<=k;i++)
	{
		p[i].s1=dis[0][vec[i]];
		p[i].s2=dis[1][vec[i]];
		p[i].st=p[i].s1-p[i].s2;
	}
	sort(p+1,p+1+k);
	int ans=0;
	int _max=p[1].s1;
	for(int i=2;i<=k;i++)
	{
		ans=max(ans,_max+p[i].s2+1);
		_max=max(_max,p[i].s1);
	}
	cout<<min(dis[0][n],ans);
	return 0;
}

努力加油a啊,(o)/~

你可能感兴趣的:(Cow and Fields CodeForces - 1307D(spfa+思维))