题目简述:
BSNY所在的城市有N个人,每个人的年龄未知。已知M对人之间的年龄大小,用ai, bi表示编号ai的人的年龄不小于编号bi人的年龄。
为了让年龄更加隐匿,BSNY想把这N个人分成若干组,每组内的成员相互不能比较出年龄大小。
现在BSNY想知道,要达到上述要求,至少分多少组?
例如N=4, M=4。
M对关系如下:1不小于2,1不小于3,2不小于4,3不小于4
至少分3组:{1}, {2,3}, {4},使得每组内两两不能比较年龄
==================================================================================================
本来以为是没重构边才造成超时,其实是因为tarjan打错。。。
思路:tarjan缩点,同一环中的点都是年龄相同的,所以要分在不同组,再拓扑dp,dp[u]=max(dp[v])+count[u]
附代码:
var n,i,ii,m,j,k,l,tot,top,num,x,y,u,v,co,ans:longint;
head,next,vet,h,nxt,vt,st,color,d,dfn,low,dp,count,dd:array[0..300005] of longint;
function min(a,b:longint):longint;
begin if a>b then exit(b);exit(a);end;
function max(a,b:longint):longint;
begin if a<b then exit(b);exit(a);end;
procedure tarjan(x:longint);
var i,v:longint;
begin
inc(num);low[x]:=num;dfn[x]:=num;
inc(top);st[top]:=x;
i:=head[x];
while i<>0 do begin
v:=vet[i];
if dfn[v]=0 then begin
tarjan(v);
low[x]:=min(low[x],low[v]);
end else
if color[v]=0 then low[x]:=min(low[x],dfn[v]);
i:=next[i];
end;
if dfn[x]=low[x] then begin
inc(co);
while st[top]<>x do begin
inc(count[co]);
color[st[top]]:=co;
//write(st[top],' ');
dec(top);
end;
inc(count[co]);
//writeln(st[top]);
color[st[top]]:=co;
dec(top);
end;
end;
function dfs(x:longint):longint;
var i,v,j,ii:longint;
begin
if dp[x]>0 then exit(dp[x]);
if d[x]=0 then begin dp[x]:=count[x];exit(dp[x]);end;
ii:=h[x];
while ii<>0 do begin
v:=vt[ii];
if v<>x then dp[x]:=max(dp[x],dfs(v));
ii:=nxt[ii];
end;
dp[x]:=dp[x]+count[x];
exit(dp[x]);
end;
begin
readln(n,m);
for i:=1 to m do begin
readln(x,y);
inc(tot);
next[tot]:=head[x];
head[x]:=tot;
vet[tot]:=y;
end;
tot:=0;
for i:=1 to n do if dfn[i]=0 then tarjan(i);
for i:=1 to n do begin
ii:=head[i];
while ii<>0 do begin
v:=vet[ii];
if color[i]<>color[v] then begin
inc(tot);nxt[tot]:=h[color[v]];h[color[v]]:=tot;vt[tot]:=color[i];
inc(dd[color[i]]); inc(d[color[v]]);
end;
ii:=next[ii];
end;
end;
//for i:=1 to n do write(color[i],' ');writeln; 调代码的好方法
//for i:=1 to co do write(count[i],' ');writeln;
//for i:=1 to co do write(dd[i],' ');writeln;
//for i:=1 to co do write(d[i],' ');writeln;
for i:=1 to co do if dd[i]=0 then ans:=max(ans,dfs(i));
writeln(ans);
end.