题意
一个有向图,要求返回从1到n的路径情况。
0:0条路 1:一条路 -1:无限条 2:多与1的有限条
思路
会出现无限的原因是因为有环的存在,可以通过tarjan算法找到连通块
tarjan找到连通块后,相应的ans[i]已经被更新成-1。
深搜所有点,如果该点ans=-1,那么其他经过他的点也是-1。
只有一条通路的,可以再次通过深搜来确定
最后一次深搜,如果有多条边到该点,则该点往后的点的ans则被更新成2
代码
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 4e5+5;
const int INF = 0x3f3f3f;
const int mod = 1e9 + 7;
const double pi = acos(-1);
inline ll read(){
ll x = 0, f = 1; char ch; ch = getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,cnt;
int vis[maxn];
vector <int> g[maxn];
int ans[maxn];
int dnf[maxn],low[maxn],in[maxn];
stack <int> st;
void init()
{
cnt=0;
while(!st.empty())
st.pop();
for(int i=1;i<=n;i++)
{
dnf[i]=low[i]=vis[i]=in[i]=ans[i]=0;
g[i].clear();
}
}
void tarjan(int u)
{
low[u]=dnf[u]=++cnt;
st.push(u);
in[u]=1;
int sz=g[u].size();
for(int i=0;i<sz;i++)
{
int v=g[u][i];
if(v==u) ans[v]=-1;
if(!dnf[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(in[v])
{
low[u]=min(low[u],low[v]);
}
}
if(dnf[u]==low[u])
{
if(st.top()==u)
{
in[st.top()]=0;
st.pop();
}
else
{
int v;
do
{
v=st.top();
st.pop();
ans[v]=-1;
in[v]=0;
}while(u!=v);
}
}
}
void sol(int son,int fa)
{
if(fa==-1)
ans[son]=-1;
if(ans[son]==-1)
return;
ans[son]=min(ans[son]+fa,2);
}
void dfs(int u)
{
if(vis[u]) return;
vis[u]=1;
int sz=g[u].size();
for(int i=0;i<sz;i++)
{
int v=g[u][i];
sol(v,ans[u]);
dfs(v);
}
}
void dfs2(int u)
{
int sz=g[u].size();
for(int i=0;i<sz;i++)
{
int v=g[u][i];
if(ans[v]==1)
{
ans[v]=2;
dfs2(v);
}
}
}
void solve() {
n=read(),m=read();
init();
for(int i=1;i<=m;i++)
{
int a,b;
a=read(),b=read();
g[a].push_back(b);
}
tarjan(1);
sol(1,1);
for(int i=1;i<=n;i++)
if(ans[i]==-1)
dfs(i);
dfs(1);
for(int i=1;i<=n;i++)
if(ans[i]==2)
dfs2(i);
for(int i=1;i<=n;i++)
cout<<ans[i]<<" ";
cout<<Endl;
return ;
}
int main() {
for(int T = read(); T; T--)
solve();
return 0;
}