bzoj1093: [ZJOI2007]最大半连通子图
2017-03-31 11:25
411 查看
传送门
首先用tarjan缩点,重建图。点的权值为DAG中点的个数。
跑一遍最长路水过。
首先用tarjan缩点,重建图。点的权值为DAG中点的个数。
跑一遍最长路水过。
uses math; var a,b,c,d,tr,lo,vis,ss,s,eda,edb,f,g,ge,co,zhan,tt,li:array [0..1000005] of longint; n,sum,h,t,ansx,ansy,m,modd,i,p,lm,j,top:longint; procedure ins(i:longint); begin c[i]:=d[a[i]]; d[a[i]]:=i; end; procedure tarjan; begin inc(h); tr[li[li[0]]]:=h; lo[li[li[0]]]:=h; vis[li[li[0]]]:=1; inc(t); f[t]:=li[li[0]]; s[li[li[0]]]:=1; ss[li[li[0]]]:=1; tt[li[li[0]]]:=d[li[li[0]]]; while (tt[li[li[0]]]<>0) do begin if (s[b[tt[li[li[0]]]]]=0) then begin li[li[0]+1]:=b[tt[li[li[0]]]]; inc(li[0]); tarjan; lo[li[li[0]]]:=min(lo[li[li[0]]],lo[b[tt[li[li[0]]]]]); end else if (ss[b[tt[li[li[0]]]]]=1) then lo[li[li[0]]]:=min(lo[li[li[0]]],tr[b[tt[li[li[0]]]]]); tt[li[li[0]]]:=c[tt[li[li[0]]]]; end; if tr[li[li[0]]]=lo[li[li[0]]] then begin inc(sum); while (f[t+1]<>li[li[0]]) do begin ss[f[t]]:=0; co[f[t]]:=sum; inc(ge[sum]); dec(t); end; end; dec(li[0]); end; procedure kp(l,r:longint); var i,j,m1,m2:longint; begin i:=l; j:=r; m1:=eda[(l+r) div 2]; m2:=edb[(l+r) div 2]; while (i<=j) do begin while (eda[i]<m1) or ((eda[i]=m1) and (edb[i]<m2)) do inc(i); while (eda[j]>m1) or ((eda[j]=m1) and (edb[j]>m2)) do dec(j); if (i<=j) then begin p:=eda[i]; eda[i]:=eda[j]; eda[j]:=p; p:=edb[i]; edb[i]:=edb[j]; edb[j]:=p; inc(i); dec(j); end; end; if (l<j) then kp(l,j); if (i<r) then kp(i,r); end; procedure work; begin tt[li[li[0]]]:=d[li[li[0]]]; g[li[li[0]]]:=1; vis[li[li[0]]]:=1; while (tt[li[li[0]]]<>0) do begin if (vis[b[tt[li[li[0]]]]]=0) then begin li[li[0]+1]:=b[tt[li[li[0]]]]; inc(li[0]); work; end; if (f[b[tt[li[li[0]]]]]>f[li[li[0]]]) then begin f[li[li[0]]]:=f[b[tt[li[li[0]]]]]; g[li[li[0]]]:=0; end; if (f[b[tt[li[li[0]]]]]=f[li[li[0]]]) then g[li[li[0]]]:=(g[li[li[0]]]+g[b[tt[li[li[0]]]]]) mod modd; tt[li[li[0]]]:=c[tt[li[li[0]]]]; end; f[li[li[0]]]:=f[li[li[0]]]+ge[li[li[0]]]; dec(li[0]); end; begin read(n,m,modd); for i:=1 to m do begin read(a[i],b[i]); ins(i); end; for i:=1 to n do if (vis[i]=0) then begin h:=0; t:=0; li[0]:=1; li[1]:=i; tarjan; end; m:=0; for i:=1 to n do begin p:=d[i]; while (p<>0) do begin if (co[a[p]]<>co[b[p]]) then begin inc(m); eda[m]:=co[a[p]]; edb[m]:=co[b[p]]; end; p:=c[p]; end; end; kp(1,m); lm:=1; for i:=2 to m do if (eda[i]<>eda[i-1]) or (edb[i]<>edb[i-1]) then begin inc(lm); eda[lm]:=eda[i]; edb[lm]:=edb[i]; end; a:=edb; b:=eda; n:=sum; m:=lm; fillchar(c,sizeof(c),0); fillchar(d,sizeof(d),0); fillchar(f,sizeof(f),0); fillchar(tt,sizeof(tt),0); for i:=1 to m do ins(i); fillchar(vis,sizeof(vis),0); for i:=1 to n do if vis[i]=0 then begin li[0]:=1; li[1]:=i; work; end; ansx:=0; ansy:=0; for i:=1 to n do begin if (ansx<f[i]) then begin ansy:=0; ansx:=f[i]; end; if (ansx=f[i]) then ansy:=(ansy+g[i]) mod modd; end; writeln(ansx); writeln(ansy); end.
相关文章推荐
- BZOJ1093: [ZJOI2007]最大半连通子图
- 【BZOJ】1093: [ZJOI2007]最大半连通子图(tarjan+拓扑序)
- BZOJ1093: [ZJOI2007]最大半连通子图
- [bzoj1093][ZJOI2007]最大半连通子图
- BZOJ 1093: [ZJOI2007]最大半连通子图|tarjan|动态规划
- BZOJ1093 [ZJOI2007]最大半连通子图
- 【连通分量】BZOJ 1093: [ZJOI2007]最大半连通子图
- bzoj1093【ZJOI2007】最大半连通子图
- BZOJ 1093: [ZJOI2007]最大半连通子图
- bzoj 1093: [ZJOI2007]最大半连通子图
- BZOJ 1093 ZJOI2007 最大半连通子图 Tarjan+动态规划
- 【BZOJ 1093】 [ZJOI2007]最大半连通子图
- bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)
- BZOJ 1093 ZJOI 2007 最大半连通子图 强联通分量+拓扑图DP
- 【bzoj1093】 [ZJOI2007]最大半连通子图
- BZOJ 1093 ZJOI 2007 最大半连通子图 DP
- BZOJ1093 [ZJOI2007]最大半连通子图 【tarjan缩点 + DAG最长路计数】
- [bzoj1093][ZJOI2007]最大半连通子图 Tarjan,DP
- BZOJ 1093 [ZJOI2007]最大半连通子图
- 【bzoj 1093】: [ZJOI2007]最大半连通子图