还是14年noip,这是day2第二题。
寻找道路
描述
在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到 终点的路径,该路径满足以下条件:
路径上的所有点的出边所指向的点都直接或间接与终点连通。
在满足条件 1 的情况下使路径最短。
注意:图 G 中可能存在重边和自环,题目保证终点没有出边。 请你输出符合条件的路径的长度。输入格式
第一行有两个用一个空格隔开的整数 n 和 m,表示图有 n 个点和 m 条边。
接下来的 m 行每行 2 个整数 x、y,之间用一个空格隔开,表示有一条边从点 x 指向点y。
最后一行有两个用一个空格隔开的整数 s、t,表示起点为 s,终点为 t。输出格式
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。
如果这样的路径不存在,输出-1。样例
样例输入1
3 2
1 2
2 1
1 3样例输出1
-1
样例输入2
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5样例输出2
3
限制
对于 30%的数据,0 < n ≤ 10,0 < m ≤ 20;
对于 60%的数据,0 < n ≤ 100,0 < m ≤ 2000;
对于 100%的数据,0 < n ≤ 10,000,0 < m ≤ 200,000,0 < x,y,s,t ≤ n,x ≠ t。提示
【输入输出样例1说明】
![]()
如上图所示,箭头表示有向道路,圆点表示城市。起点 1 与终点 3 不连通,所以满足题目描述的路径不存在,故输出-1。
【输入输出样例2说明】
![]()
如上图所示,满足条件的路径为 1->3->4->5。注意点 2 不能在答案路径中,因为点 2 连了一条边到点 6,而点 6 不与终点 5 连通。来源
NOIP2014 提高组 Day2
图片来源vijos
这道题是day2的图论题,day1的图论我一分没得,day2结果我也只得了10分,萎得不行,这道题不难,也不太会超时,思想比较简单,我也就简单地说一下吧。
首先就是筛点,把所有可以选的点筛出来,然后再在筛出来的点上面跑SPFA,找到S和T之间的最短路就可以了。
筛点可以先存一个反向图,再从T点用bfs,判断每个点能不能到T,然后在判断是不是所用它连接的点也可以到T,这里可以用入度,每次找到,入度减一,如果最后入度为0,那么就可以选这个点,不为0就要筛出去。
筛点后直接SPFA,比较简单这里不再赘述。
话不多说,代码见下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define M 200005
#define N 10005
#define INF (1<<30)
using namespace std;
int first[N],next[M],to[M],flag[M],t,can[N];
int first2[N],next2[M],to2[M],t2;
int n,m,S,T,d,l[N],b[N],vis[N],c[N];
void addedge(int s,int v)
{
next[++t]=first[s];
first[s]=t;
to[t]=v;
}
void addedge2(int s,int v)
{
next2[++t2]=first2[s];
first2[s]=t;
to2[t]=v;
c[v]++;
}
void dfs(int x)
{
if(vis[x])return ;
vis[x]=1;
if(!first2[x])return ;
for(int i=first2[x];i!=0;i=next2[i])
{
int v=to2[i];
c[v]--;
dfs(v);
}
}
void SPFA()
{
queue<int>Q;
while(!Q.empty())Q.pop();
l[S]=0;
Q.push(S);
while(!Q.empty())
{
int s=Q.front();Q.pop();
for(int i=first[s];i!=0;i=next[i])
{
int v=to[i];
if(!can[v])continue;
if(l[v]>l[s]+1)
{
l[v]=l[s]+1;
Q.push(v);
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int s,t;
scanf("%d%d",&s,&t);
if(s!=t)addedge(s,t);
if(s!=t)addedge2(t,s);
}
cin>>S>>T;
dfs(T);
for(int i=1;i<=n;i++)
if(!c[i]&&vis[i])can[i]=1;
for(int i=1;i<=n;i++)l[i]=INF;
SPFA();
int ans;
if(l[T]>=INF)ans=-1;
else ans=l[T];
cout<<ans;
return 0;
}
如果有什么问题,或错误,请在评论区提出,谢谢。