版权声明:JCBP工作室 & A.pro https://blog.csdn.net/Apro1066/article/details/82833103
题目描述
给出N个点,M条边的有向图,对于每个vv,求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% 的数据,1≤N.K≤10^3;
• 对于100% 的数据,1≤N,M≤10^5。
思路
刚学图论。。直接dfs肯定错,这是有向图的遍历,遍历顺序是与存边顺序有关的。此题看了一下题解,都说图反向建边然后搜索遍历。有多个点到一个点可以转成一个点到多个点(反向),每个点都搜一次。
这个代码是我借鉴别人的。有部分注释没写是因为不是很理解。以后理解了就补上。
#include <stdio.h>
#include <iostream>
using namespace std;
int n,m,s;
int a[100001],b[100001],to[100001],visit[100001];
void dfs(int now,int i)//i记录初始点,now是现在的点
{
register int j;
if(visit[now])//这个点被访问过了
{
return;
}
visit[now]=i;//现在就访问当前的点
for(j=b[now];j;j=a[j])
{
if(visit[to[j]]==0)
{
dfs(to[j],i);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int x,y,i,j;
cin>>n>>m;//输入n个点,m条边
for(i=1,s=1;i<=m;i++,s++)//开始建立有向图
{
cin>>x>>y;
a[s]=b[y];//建图
b[y]=s;
to[s]=x;//这是有向图,所以需要方向记录
}
for(i=n;i>=1;i--)//反向找最大点
{
dfs(i,i);
}
for(i=1;i<=n;i++)
{
cout<<visit[i]<<' ';
}
return 0;
}