#include using namespace std; const int N = 100010; int n; //n个结点 int m; //m条边 int res[N]; int u, v; vector p[N]; //vector存图 /** 基本思想: 反向建边是逆向思维,这样dfs时可以通过打标记来更便捷地记录某点所能到达的最大点, 而正向建边dfs时可能会重复搜索,遍历整个图,会增大复杂度 感悟:正向建边TLE时,考虑一下反向建边 */ /** * 功能:填充每个结点能够到达的最大结点号 * @param x 哪个结点 * @param d 最大结点号 */ void dfs(int x, int d) { if (res[x]) return; //访问过 res[x] = d; for (int i = 0; i < p[x].size(); i++) dfs(p[x][i], d); } int main() { //读入 scanf("%d%d", &n, &m); //构建图 for (int i = 1; i <= m; i++) { scanf("%d%d", &u, &v); p[v].push_back(u); //反向建边 } //从大到小,逐个深度优先搜索 for (int i = n; i; i--) dfs(i, i); //输出每个结点的最大到达结点号 for (int i = 1; i <= n; i++) printf("%d ", res[i]); printf("\n"); return 0; }