题目链接
题意:真是个恶心的题目,又臭又长,比赛的时候看的都快吐了。
其实就是给定一个有向图,和一个初始路径,你从初始路径一直走,当走到i时发现i到终点的最短路径和给出的初始路径不一样,系统就会重建,求重建的最小和最大次数。
思路:这题感觉完全在考你英文水平,知道题意后秒解,由于是有向图,所以需要反向建边,spfa求出n到各个点的最短路,假设当前点为x,对应初始路径是a【i】,显然如果d【x】和d【a【i】】相等并且x不等于a【i】的时候,最大次数+1,如果d【x】<d【a【i】】的时候系统肯定是要重建的无法避免的,最大和最小次数都要+1。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+1;
const int inf=0x3f3f3f3f;
int n,m,k,d[maxn],a[maxn],ans1,ans2;
bool vis[maxn];
vector<int>g1[maxn],g2[maxn];
void spfa(int x)
{
memset(vis,false,sizeof(vis));
for(int i=0;i<maxn;++i) d[i]=inf;
d[x]=0;
queue<int>q;
q.push(x);
vis[x]=true;
while(!q.empty())
{
int top=q.front();
q.pop();
vis[top]=false;
for(auto v:g2[top])
{
if(d[top]+1<d[v])
{
d[v]=d[top]+1;
if(!vis[v]) q.push(v),vis[v]=true;
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;++i)
{
scanf("%d%d",&u,&v);
g1[u].push_back(v);
g2[v].push_back(u);
}
scanf("%d",&k);
for(int i=1;i<=k;++i) scanf("%d",&a[i]);
spfa(a[k]);
for(int i=1;i<k;++i)
{
int flag1=0,flag2=0;
for(int v:g1[a[i]])
{
if(v==a[i+1]) continue;
if(d[v]==d[a[i+1]]) flag1=1;
else if(d[v]<d[a[i+1]]) flag2=1;
}
if(flag2) ans1++,ans2++;
else if(flag1) ans2++;
}
printf("%d %d\n",ans1,ans2);
}