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位小数。

 

输入输出样例

输入样例#1: 复制
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
输出样例#1: 复制
OK
OK
ILLEGAL
2.0000
OK
3.0000
ILLEGAL
OK
ILLEGAL

说明

对于100\%100%的数据,N≤100000,Q≤300000,1≤u,v≤NN100000,Q300000,1u,vN

本题是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 }
View Code

 

posted @ 2018-12-27 23:59  zjxxcn  阅读(196)  评论(0编辑  收藏  举报