bzoj2791
2015-06-04 19:44
134 查看
每个顶点有且仅有一条出边是什么意思呢
类似一棵树,树上的边都是由儿子指向父亲的,并且这个东西带着一个环
也就是一个个有向环套有向树……
这题还是比较简单的,把环作为根然后类似lca做即可,注意细节的panding
View Code
类似一棵树,树上的边都是由儿子指向父亲的,并且这个东西带着一个环
也就是一个个有向环套有向树……
这题还是比较简单的,把环作为根然后类似lca做即可,注意细节的panding
type node=record po,next:longint; end; var e:array[0..500010] of node; s,p,w,c,be,d,q:array[0..500010] of longint; v:array[0..500010] of boolean; anc:array[0..500010,0..20] of longint; t,f,r,n,m,len,i,x,y,a,b:longint; function max(a,b:longint):longint; begin if a>b then exit(a) else exit(b); end; function min(a,b:longint):longint; begin if a>b then exit(b) else exit(a); end; procedure swap(var a,b:longint); var c:longint; begin c:=a; a:=b; b:=c; end; procedure add(x,y:longint); begin inc(len); e[len].po:=y; e[len].next:=p[x]; p[x]:=len; end; procedure bfs; var x,i,y:longint; begin f:=1; while f<=r do begin x:=q[f]; for i:=1 to 20 do begin y:=anc[x,i-1]; if y<>0 then anc[x,i]:=anc[y,i-1] else break; end; i:=p[x]; while i<>0 do begin y:=e[i].po; if not v[y] then begin d[y]:=d[x]+1; anc[y,0]:=x; be[y]:=t; inc(r); q[r]:=y; v[y]:=true; end; i:=e[i].next; end; inc(f); end; end; procedure lca(x,y:longint); var i,num,a1,b1,a2,b2:longint; begin a:=0; b:=0; if d[x]>d[y] then for i:=20 downto 0 do if d[x]-1 shl i>=d[y] then begin x:=anc[x,i]; a:=a+1 shl i; end; if d[y]>d[x] then for i:=20 downto 0 do if d[y]-1 shl i>=d[x] then begin y:=anc[y,i]; b:=b+1 shl i; end; if x=y then exit; for i:=20 downto 0 do if (anc[x,i]<>anc[y,i]) then begin x:=anc[x,i]; a:=a+1 shl i; y:=anc[y,i]; b:=b+1 shl i; end; if (anc[x,0]=anc[y,0]) and (anc[x,0]<>0) then begin inc(a); inc(b); exit; end; num:=s[be[x]]; if c[x]>c[y] then a1:=a+num-c[x]+c[y] else a1:=a+c[y]-c[x]; b1:=b; a2:=a; if c[x]<c[y] then b2:=b+num-c[y]+c[x] else b2:=b+c[x]-c[y]; if max(a1,b1)=max(a2,b2) then begin if (min(a1,b1)>min(a2,b2)) or (min(a1,b1)=min(a2,b2)) and (a1<b1) then begin a:=a2; b:=b2; end else begin a:=a1; b:=b1; end; end else if max(a1,b1)>max(a2,b2) then begin a:=a2; b:=b2; end else begin a:=a1; b:=b1; end; end; begin readln(n,m); for i:=1 to n do begin read(w[i]); add(w[i],i); end; for i:=1 to n do if be[i]=0 then begin inc(t); be[i]:=t; x:=i; while true do begin x:=w[x]; if be[x]=t then break; be[x]:=t; end; y:=x; r:=0; repeat inc(s[t]); c[y]:=s[t]; inc(r); q[r]:=y; v[y]:=true; y:=w[y]; until y=x; bfs; end; for i:=1 to m do begin readln(x,y); if be[x]<>be[y] then begin writeln('-1 -1'); continue; end; lca(x,y); writeln(a,' ',b); end; end.
View Code
相关文章推荐
- 第二阶段冲刺第四天
- math库
- 数据结构实验之栈三:后缀式求值
- [转载]JAVA中this用法小结
- cmake的使用实例: opencv-3.0.0-alpha安装
- 最完美的Linux桌面软件
- Lexus Extroic OpenCart 2.X 自适应主题模板 ABC-0648-01
- Regular Expression Matching
- ios之改变label的行间距
- sping_aop_日志
- 合天解密200-找茬游戏
- 【unity3D】鼠标控制camera的移动、放大(俯视浏览效果、LOL摄像机移动效果)
- iOS 学习资料整理
- 客运综合管理系统项目—附加(数据的导出)
- 心静是一种境界
- Genymotion插件安装教程
- NSNumber
- 冲刺第二阶段第三天
- C++ 智能指针类
- Lexus Extroic OpenCart 2.X 自适应主题模板 ABC-0648-01