图的遍历
题目描述
给出 N N N 个点, M M M 条边的有向图,对于每个点 v v v,求 A ( v ) A(v) A(v) 表示从点 v v v 出发,能到达的编号最大的点。
输入格式
第 1 1 1 行 2 2 2 个整数 N , M N,M N,M,表示点数和边数。
接下来 M M M 行,每行 2 2 2 个整数 U i , V i U_i,V_i Ui,Vi,表示边 ( U i , V i ) (U_i,V_i) (Ui,Vi)。点用 1 , 2 , … , N 1,2,\dots,N 1,2,…,N 编号。
输出格式
一行 N N N 个整数 A ( 1 ) , A ( 2 ) , … , A ( N ) A(1),A(2),\dots,A(N) A(1),A(2),…,A(N)。
样例 #1
样例输入 #1
4 3
1 2
2 4
4 3
样例输出 #1
4 4 3 4
提示
- 对于 60 % 60\% 60% 的数据, 1 ≤ N , M ≤ 1 0 3 1 \leq N,M \leq 10^3 1≤N,M≤103。
- 对于 100 % 100\% 100% 的数据, 1 ≤ N , M ≤ 1 0 5 1 \leq N,M \leq 10^5 1≤N,M≤105。
满分题解:https://www.luogu.com.cn/article/cuelm1wr
主要思路:与其思考如何到达最大的点,不如思考较大的点能够到达的点。然后使用vis数组防止重复访问,提高运行效率
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
#define MAXL 100010
int N, M, A[MAXL];
vector<int> G[MAXL]; //vector存图
void dfs(int x, int d) {
if(A[x]) return; //访问过
A[x] = d;
for(int i=0; i<G[x].size(); i++)
dfs(G[x][i], d);
}
int main() {
int u, v;
scanf("%d%d", &N, &M);
for(int i=1; i<=M; i++) {
scanf("%d%d", &u, &v);
G[v].push_back(u); //反向建边
}
for(int i=N; i; i--) dfs(i, i);
for(int i=1; i<=N; i++) printf("%d ", A[i]);
printf("\n");
return 0;
}
个人思路1:与满分题解类似,只不过没有思考到从最大的点开始遍历dfs,导致有一个测试样例超时(使用vis形同虚设,因为同一个点需要反复更新)
个人思路2: 20分。妄图使用拓扑结构来遍历整个图,却不知序号最大的点未必是出度为0的点。
#include <bits/stdc++.h>
using namespace std;
vector<int> from[100055];
bool vis[100005] = {0};
int ans[100055] = {0},ru[100005] = {0};
int n,m;
void dfs()
{
// cout<<now<<' '<<anss<<endl;
stack<int> s;
for(int i = 1;i<=n;i++)
if(ru[i] == 0)
s.push(i);
while(!s.empty())
{
int a = s.top();//cout<<a<<endl;
s.pop();
vector<int>::iterator it = from[a].begin();
for(;it!=from[a].end();it++)
{
if(ans[*it]<ans[a])
{
ans[*it] = ans[a];
// cout<<*it<<' '<<ans[*it]<<endl;
// s.push(*it);
// vis[*it] = true;
}
ru[*it]--;
if(ru[*it] == 0) s.push(*it);
}
// }
}}
int main()
{
cin>>n>>m;
for(int i = 0;i<=n;i++)
{
from[i].clear();
}
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
from[b].push_back(a);
ru[a]++;
}
cout<<ru[37]<<endl;
for(int i=1;i<=n;i++) ans[i] = i;
// for(int i=1;i<=n;i++)
// {
// if(vis[i] == false) dfs(i);
cout<<ans[i]<<' ';
// }
dfs();
for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
}