题解 P2296 【寻找道路】
分别顺序 逆序 储存边 先逆向跑一边 找出能到的点 再跑一边SPFA 先跑一边 我统计从终点出发的点 被访问过几次 被访问的次数等于出边数 就是合法的 签到题
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
vector<int>p[10010];//ni
int ru[10010]={0};
int chu[10010]={0};
bool map[10010];
bool vis[10010];
int n,m;
int s,t;
queue<int>q;
queue<int>Q;
int dis[10010];
int ans[10010];
vector<int>P[10010];//shun
void bfs(int x)
{
while(!Q.empty())
{
int tmp=Q.front();
Q.pop();
int l=p[tmp].size();
for(int i=0;i<l;i++)
{
int temp=p[tmp][i];
if(i==1)
{
}
ans[temp]++;
if(vis[temp])
{
Q.push(temp);
vis[temp]=false;
}
}
}
}
void spfa(int x)
{
while(!q.empty())
{
int tmp=q.front();
q.pop();
int t=P[tmp].size();
for(int i=0;i<t;i++)
{
int temp=P[tmp][i];
if(map[temp]&&vis[temp])
{
if(dis[temp]>dis[tmp]+1)
{
dis[temp]=dis[tmp]+1;
q.push(temp);
vis[temp]=false;
}
}
}
vis[tmp]=true;
}
}
int main()
{
memset(dis,127,sizeof(dis));
memset(vis,true,sizeof(vis));
memset(map,false,sizeof(map));
memset(ans,0,sizeof(ans));
memset(chu,0,sizeof(chu));
memset(ru,0,sizeof(ru));
int x,y;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
map[i]=true;
}
for(int i=1;i<=m;i++)
{
cin>>x>>y;
if(x!=y)
{
P[x].push_back(y);
p[y].push_back(x);
chu[x]++;
ru[y]++;
}
}
cin>>s>>t;
map[t]=true;
Q.push(t);
bfs(t);
for(int i=1;i<=n;i++)
{
if(ans[i]==chu[i]&&chu[i]!=0)
{
map[i]=true;
}
else
{
map[i]=false;
}
}
map[t]=true;
memset(vis,true,sizeof(vis));
dis[s]=0;
q.push(s);
spfa(s);
if(dis[t]>99999)
{
cout<<"-1";
}
else
{
cout<<dis[t];
}
return 0;
}