图的遍历(dfs)
题目描述
给出N个点,M条边的有向图,对于每个点v,求A(v)表示从点v出发,能到达的编号最大的点。
输入格式
第1 行,2 个整数N,M。
接下来MM行,每行2个整数Ui,Vi,表示边(Ui,Vi)。点用1,2,⋯,N编号。
输出格式
N 个整数A(1),A(2),⋯,A(N)。
输入输出样例
输入 #1
4 3 1 2 2 4 4 3
输出 #1
4 4 3 4
说明/提示
• 对于60% 的数据,10^31≤N.M≤103;
• 对于100% 的数据,10^51≤N,M≤105。
分析:
深度优先遍历
(1)任选G中某个未被访问的顶点v,访问v
(2)以与v相关联的每一个未被访问过的顶点w出发深度优先遍历G
(3)若G中还有未被访问的顶点,则转(1)否则遍历终止。
//图的遍历
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=1e5+10;
int vis[maxn],ans[maxn],head[maxn],cnt=0,n,m,temp=0;
//vis记录是否遍历过
struct n
{
int to,next;
}e[maxn];
void add(int u,int v)
{
e[cnt].to=v;//指向谁
e[cnt].next=head[u];
head[u]=cnt++;
}
void dfs(int u)
{
vis[u]=1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(!vis[v]) dfs(v);
}
ans[u]=temp;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
head[i]=-1;
ans[i]=i;
}
for(int i=1,a,b;i<=m;i++)
{
cin>>a>>b;
add(b,a);
}
for(int i=n;i>=1;i--)
{
if(!vis[i])
{
temp=i;
dfs(i);
}
}
for(int i=1;i<=n;i++)
{
cout<<ans[i]<<" ";
}
return 0;
}