题目描述:
给出N个点,M条边的有向图,对于每个点v,求A(v)表示从点v出发,能到达的编号最大的点。
输入:第1 行,2 个整数N,M。
接下来M行,每行2个整数Ui、Vi,表示边(Ui,Vi)。点用1,2,⋯,N编号。
输出:N 个整数A(1),A(2),⋯,A(N)。
输入样例:
4 3 1 2 2 4 4 3
输出样例:
4 4 3 4
解题思路:
求图中各结点能到达的最大结点,正向思路的话可以循环正向遍历结点,定义一个最大值变量记录该结点能到达的最大值结点,然后结合DFS遍历其所有能到达的结点,随时更新最大值变量,这是可行的。
为了简化可以采取逆向思路,采用反向建图的方式做出逆向图,从最大结点n开始DFS,凡是能遍历的结点,其正向图总最大能到达结点就是n,将记录保存在数组中。之后从次大结点再开始DFS,直到填满记录数组。
代码实现:
#include <iostream>
using namespace std;
#define maxn 100001
int maxv[maxn]; //记录能到达的最大结点
int head[maxn];
int m, n, cnt;
class Edge
{
public:
int to;
int next;
};
Edge edge[maxn];
void InsertEdge(int u, int v)
{
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void CreateG()
{
memset(head, -1, sizeof(head));
cin >> n >> m;
int u = 0, v = 0;
for (int i = 0; i < m; i++)
{
cin >> u >> v;
InsertEdge(v, u);
}
}
void DFS(int v, int max)
{
if (maxv[v])
{
return;
}
maxv[v] = max;
for (int i = head[v]; i != -1; i = edge[i].next)
{
DFS(edge[i].to, max);
}
}
int main()
{
CreateG();
for (int i = n; i > 0; i--)
{
DFS(i, i);
}
for (int i = 1; i <= n; i++)
{
cout << maxv[i] << " ";
}
return 0;
}