[GRYZ2015]Graph
题目描述
给出 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
数据范围
对于 60% 的数据,1 ≤ N,K ≤ 10^3
对于 100% 的数据,1 ≤ N,M ≤ 10^5。
思路
图的遍历。DFS。
用邻接矩阵不开动态数组60分。
var f:array[1..2000000,1..2000000] of boolean; ff:packed array[1..10000] of boolean; a:array[1..10000] of longint; n,m,i,sum,y,z:longint; function max(a,b:longint):longint; begin if a>b then exit(a) else exit(b); end; procedure dfs(x:longint); var i:longint; begin ff[x]:=true; sum:=max(sum,x); for i:=1 to n do if (f[x,i])and(not ff[i]) then dfs(i); end; procedure intt; begin assign(input,'graph.in'); assign(output,'graph.out'); reset(input); rewrite(output); end; procedure outt; begin close(input); close(output); end; begin //intt; writeln(sizeof(f) div 1024 div 1024); fillchar(f,sizeof(f),false); readln(n,m); for i:=1 to m do begin readln(y,z); f[y,z]:=true; end; for i:=1 to n do begin fillchar (ff,sizeof(ff),false); sum:=0; dfs(i); a[i]:=sum; end; for i:=1 to n do write(a[i],' '); //outt; end.
如果可以用动态数组的话或许可以多卡几个点。
用边表存储可以A掉。
program df; var head,f:array[1..100000]of longint; next,v:array[1..100000]of longint; b:array[1..100000]of boolean; n,i,m,j,a1,a2,max:longint; procedure dfs(a1:longint); var b1:longint; begin if b[a1] then exit; b[a1]:=true; f[a1]:=max; b1:=head[a1]; while b1<>0 do begin dfs(v[b1]); b1:=next[b1]; end; end; begin assign(input,'graph.in'); assign(output,'graph.out'); reset(input); rewrite(output); read(n,m); for i:=1 to m do begin read(a1,a2); next[i]:=head[a2]; head[a2]:=i; v[i]:=a1; end; for i:=n downto 1 do if not b[i] then begin max:=i; dfs(i); end; for i:=1 to n-1 do write(f[i],' '); writeln(f[n]); close(input); close(output); end.
强连通分量
拓扑排序
DP/BFS
同样可以求解此题。