luogu U19464 山村游历
题目背景
题目摘自WC模拟试题(by Philipsweng),数据自测,如有问题欢迎反馈
题目描述
在一个偏远的小镇上,有一些落后的山村。山村之间通过一些道路来连接。当然有的山村可能不连通。
一年当中会发生很多大事,比如说有人提议要在山村ii与jj之间修建一条道路,也有人觉得山村ii和jj之间的道路需要被拆掉。
由于小镇的落后,镇长不会允许存在两个山村i,ji,j,他们存在超过一条路径到达对方。也就是说,假如在修建山村i,ji,j之间的道路之前,它们已经连通了,那么这条道路就不会被修建。
但拆除道路就不一样了。假如有人建议拆除连接i,ji,j的道路,并且i,ji,j的确有道路相连的话,镇长就会把它拆掉。
除了道路的修建与拆迁外,热情的山村人也会到处拜访其他人。有的时候来自山村ii的人会想到山村jj玩。
但山村人都是不识路的,那怎么办?他们有一种奇怪的遍历方式。
设一次旅行的起点为S,终点为T,点u的边集为V(i),那么这个走路过程可以用下面的伪代码来表示。
function DFS(u)
if u==T then
finish search
flag[u]<-true
random shuffle the vertices order in V(u)
//here all permutations have equal probability to be chosen
for i in V(u) do
if flag[i]==false then
count++;
DFS(i);
count++;
最后count就是这次旅行所花时间。
很显然对于一次旅行,count可能有多种取值,那么对于这次旅行时间的评估,就是count的期望。
对于每次旅行,你都要告诉山村人他这次旅行时间的评估是多少。
一开始所有的山村之间都是没有道路连接的。
update:伪代码好难看,来个cpp......
int count=0;
void dfs(int u)
{
if(u==T)cout<<count,exit(0);
flag[u]=true;
random_shuffle(V[u],V[u]+len[u]);
for(i=0;i<len[u];++i)
if(!flag[V[i]])count++,dfs(V[i]);
count++;
}
输入输出格式
输入格式:
第一行两个整数N,QN,Q,表示小镇上总共有NN个山村,一年中发生了QQ件大事。
接下来QQ行,每行包括三个整数type,u,vtype,u,v。
- 若type=0type=0,表示有人建议在u,vu,v之间修建一条道路。
- 若type=1type=1,表示有人建议拆除u,vu,v之间的道路。
- 若type=2type=2,表示山村人要进行一次uu出发到vv结束的旅行。
输出格式:
输出共Q行。
对于第i件大事,若type=0type=0或11,假如这件大事能完成,则输出OK,否则输出ILLEGAL。若type=2type=2,假如这次旅行能到达终点,则输出对应的时间评估,否则输出ILLEGAL。
对于每个时间评估,输出保留4位小数。
输入输出样例
4 9 0 1 2 0 2 4 0 4 1 2 1 4 0 2 3 2 1 4 1 4 1 1 3 2 2 1 3
OK OK ILLEGAL 2.0000 OK 3.0000 ILLEGAL OK ILLEGAL
说明
对于100\%100%的数据,N≤100000,Q≤300000,1≤u,v≤NN≤100000,Q≤300000,1≤u,v≤N
本题是lct求期望,有结论是x到y的期望就是x到y之间点的个数减一,所以我们只要用lct维护子树信息就可以(原树和虚子树)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define re register 4 #define R re int 5 #define rep(i,a,b) for(R i=a;i<=b;i++) 6 #define Rep(i,a,b) for(R i=a;i>=b;i--) 7 #define ms(i,a) memset(a,i,sizeof(a)) 8 #define lc ch[x][0] 9 #define rc ch[x][1] 10 #define pa fa[x] 11 #define I inline int 12 template<class T>I read(T &x){ 13 x=0; char c=0; 14 while (!isdigit(c)) c=getchar(); 15 while (isdigit(c)) x=x*10+(c^48),c=getchar(); 16 } 17 int const N=100001; 18 int const M=300001; 19 int st[N],top,n,m; 20 struct Lct{ 21 int ch[N][2],r[N],fa[N],s[N],si[N]; 22 I get(int x){return ch[pa][1]==x;} 23 I isr(int x){return ch[pa][0]!=x && ch[pa][1]!=x;} 24 I update(int x){s[x]=s[lc]+s[rc]+si[x]+1;} 25 I con(int x,int y,int z){fa[x]=y; ch[y][z]=x;} 26 I rotate(int x){ 27 int f=fa[x],g=fa[f],c=get(x),cc=get(f); 28 if(!isr(f)) ch[g][cc]=x; fa[x]=g; 29 con(ch[x][c^1],f,c); con(f,x,c^1); 30 update(f); update(x); 31 } 32 I pushd(int x){ 33 if(!r[x]) return 0; 34 swap(ch[lc][0],ch[lc][1]); swap(ch[rc][0],ch[rc][1]); 35 r[lc]^=1; r[rc]^=1; r[x]=0; 36 } 37 I splay(int x){ 38 top=0; int k=x; while (!isr(k)) st[++top]=k,k=fa[k]; ; st[++top]=k; 39 while (top) pushd(st[top--]); 40 for ( ; !isr(x); rotate(x)){ 41 if(!isr(pa)) rotate(get(x)==get(pa)? pa:x); 42 } 43 } 44 I access(int x){ 45 for(int y=0;x;y=x,x=pa){ 46 splay(x); 47 si[x]+=s[rc]; 48 si[x]-=s[rc=y]; 49 update(x); 50 } 51 } 52 I make(int x){ access(x); splay(x);r[x]^=1; swap(lc,rc);} 53 I find(int x){access(x);splay(x);while (lc) pushd(x),x=lc; return x;} 54 I split(int x,int y){make(x); access(y);splay(y);} 55 I cut(int x,int y){ 56 make(x); 57 if(find(y)==x && fa[x]==y && !rc){ 58 fa[x]=ch[y][0]=0; update(y);return 1; 59 }else return 0; 60 } 61 I link(int x,int y){ 62 make(x); 63 if(find(y)==x) return 0; 64 si[fa[x]=y]+=s[x]; update(y); 65 return 1; 66 } 67 }lct; 68 int main(){ 69 read(n); read(m); 70 rep(i,1,n) lct.s[i]=1; 71 while (m--){ 72 int x,y,z; read(z); read(x); read(y); 73 if(z==0) { 74 if(lct.link(x,y)) puts("OK"); 75 else puts("ILLEGAL"); 76 int t=lct.find(x); 77 } 78 if(z==1){ 79 if(lct.cut(x,y)) puts("OK"); 80 else puts("ILLEGAL"); 81 } 82 if(z==2){ 83 if(lct.find(x)!=lct.find(y)) puts("ILLEGAL"); 84 else { 85 lct.split(x,y); 86 printf("%d.0000\n",lct.s[y]-lct.si[y]-1); 87 } 88 } 89 } 90 return 0; 91 }