Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 446  Solved: 129

Description

兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海陆空交通设施发达。濑户内海沿岸气候温暖,多晴天,有日本少见的贸易良港神户港所在的神户市和曾是豪族城邑“城下町”的姬路市等大城市,还有以疗养地而闻名的六甲山地等。
兵库县官方也大力发展旅游,为了方便,他们在县内的N个旅游景点上建立了n-1条观光道,构成了一棵图论中的树。同时他们推出了M条观光线路,每条线路由两个节点x和y指定,经过的旅游景点就是树上x到y的唯一路径上的点。保证一条路径只出现一次。
你和你的朋友打算前往兵库县旅游,但旅行社还没有告知你们最终选择的观光线路是哪一条(假设是线路A)。这时候你得到了一个消息:在兵库北有一群丧心病狂的香菜蜜,他们已经选定了一条观光线路(假设是线路B),对这条路线上的所有景点都释放了【精神污染】。这个计划还有可能影响其他的线路,比如有四个景点1-2-3-4,而【精神污染】的路径是1-4,那么1-3,2-4,1-2等路径也被视为被完全污染了。
现在你想知道的是,假设随便选择两条不同的路径A和B,存在一条路径使得如果这条路径被污染,另一条路径也被污染的概率。换句话说,一条路径被另一条路径包含的概率。
 

 

Input

第一行两个整数N,M
接下来N-1行,每行两个数a,b,表示A和B之间有一条观光道。
接下来M行,每行两个数x,y,表示一条旅游线路。
 

 

Output

所求的概率,以最简分数形式输出。
 

 

Sample Input

5 3
1 2
2 3
3 4
2 5
3 5
2 5
1 4

Sample Output

1/3
样例解释
可以选择的路径对有(1,2),(1,3),(2,3),只有路径1完全覆盖路径2。

HINT

 

100%的数据满足:N,M<=100000

 

Source

 

辣鸡破题耗我时间颓我青春

 

解法一:dfs序+主席树

“如果路径A包含于路径B 那么就有A的两端点在路径B上”

主席树以dfs序为“时间轴”维护dfs序区间上的信息(可持久化树树?

树上的主席树和序列上的主席树差不多一个意思,只是提取区间时候从root[后]-root[前]变成了root[x]-root[LCA]

搞出树的DFS序,对于每条链(x,y),在x的dfs序位置差分标记y的子树区间。查询每条链(x,y)时,利用主席树提取出(x,LCA(x,y))和(y,LCA(x,y))这两段链上面的标记,就可以知道有多少链被当前的链包含。

每条链统计答案的时候要减去自己。

概率就是有污染的道路对的数量除以全部道路对的数量。

我猜没人能看懂上面说了啥,还是左转popoQQQ大爷的讲解吧http://blog.csdn.net/PoPoQQQ/article/details/43122821

破题卡内存丧心病狂。内存计算经验不足(你根本就懒得算吧喂),卡了一页MLE。

真是对不起学姐号的AC率啊。

  1 /*by SilverN*/
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<vector>
  8 #define LL long long
  9 using namespace std;
 10 const int mxn=100005;
 11 int read(){
 12     int x=0,f=1;char ch=getchar();
 13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 15     return x*f;
 16 }
 17 struct edge{
 18     int v,nxt;
 19 }e[mxn<<1];
 20 int hd[mxn],mct=0;
 21 void add_edge(int u,int v){
 22     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
 23 }
 24 //
 25 int fa[mxn],sz[mxn],top[mxn],son[mxn];
 26 int ind[mxn],out[mxn],dtime=0;
 27 int dep[mxn];
 28 void DFS1(int u){
 29     dep[u]=dep[fa[u]]+1;
 30     sz[u]=1;
 31     for(int i=hd[u];i;i=e[i].nxt){
 32         if(e[i].v==fa[u])continue;
 33         fa[e[i].v]=u;
 34         DFS1(e[i].v);
 35         sz[u]+=sz[e[i].v];
 36         if(sz[e[i].v]>sz[son[u]])son[u]=e[i].v;
 37     }
 38     return;
 39 }
 40 void DFS2(int u,int tp){
 41     ind[u]=++dtime;
 42     top[u]=tp;
 43     if(son[u]){
 44         DFS2(son[u],tp);
 45         for(int i=hd[u];i;i=e[i].nxt)
 46             if(e[i].v!=fa[u] && e[i].v!=son[u])DFS2(e[i].v,e[i].v);
 47     }
 48     out[u]=++dtime;
 49     return;
 50 }
 51 int LCA(int x,int y){
 52     while(top[x]!=top[y]){
 53         if(dep[top[x]]<dep[top[y]])swap(x,y);
 54         x=fa[top[x]];
 55     }
 56     return dep[x]<dep[y]?x:y;
 57 }
 58 //
 59 vector<int>ch[mxn];
 60 struct node{
 61     int l,r;
 62     int smm;
 63 }t[mxn*40];
 64 int rot[mxn*8],sct=0;
 65 void insert(int p,short v,int l,int r,int y,int &rt){
 66     rt=++sct;
 67     t[rt]=t[y];
 68     if(l==r){t[rt].smm+=v;return;}
 69     int mid=(l+r)>>1;
 70     if(p<=mid) insert(p,v,l,mid,t[y].l,t[rt].l);
 71     else insert(p,v,mid+1,r,t[y].r,t[rt].r);
 72     t[rt].smm=t[t[rt].l].smm+t[t[rt].r].smm;
 73     return;
 74 }
 75 int query(int L,int R,int l,int r,int R1,int R2,int R3,int R4){
 76     if(L<=l && r<=R){
 77         return t[R1].smm-t[R3].smm-t[R4].smm+t[R2].smm;
 78         //左端点+右端点-LCA-LCA以上的链 
 79     }
 80     int mid=(l+r)>>1;
 81     int res=0;
 82     if(L<=mid)res+=query(L,R,l,mid,t[R1].l,t[R2].l,t[R3].l,t[R4].l);
 83     if(R>mid)res+=query(L,R,mid+1,r,t[R1].r,t[R2].r,t[R3].r,t[R4].r);
 84     return res;
 85 }
 86 int n,m,ed;
 87 void DFS3(int u){
 88     int tmp=rot[u];
 89     rot[u]=rot[fa[u]];
 90     for(int i=0;i<ch[u].size();i++){
 91         int v=ch[u][i];
 92         insert(ind[v],1,1,ed,rot[u],tmp);
 93         rot[u]=tmp;
 94         insert(out[v],-1,1,ed,rot[u],tmp);
 95         rot[u]=tmp;
 96     }
 97     for(int i=hd[u];i;i=e[i].nxt){
 98         if(e[i].v==fa[u])continue;
 99         DFS3(e[i].v);
100     }
101     return;
102 }
103 //
104 struct mach{
105     int x,y;
106     bool operator < (const mach &b)const{
107         return (x==b.x && y<b.y)||(x<b.x);
108     }
109 }a[mxn];
110 LL gcd(LL a,LL b){return (!b)?a:gcd(b,a%b);}
111 int main(){
112     int i,j,u,v;
113     n=read();m=read();
114     for(i=1;i<n;i++){
115         u=read();v=read();
116         add_edge(u,v);add_edge(v,u);
117     }
118     DFS1(1);DFS2(1,1);
119     for(i=1;i<=m;i++){
120         a[i].x=read();a[i].y=read();
121         ch[a[i].x].push_back(a[i].y);
122     }
123     ed=dtime;
124     sort(a+1,a+m+1);
125     DFS3(1);
126     LL up=0,down=(LL)m*(m-1)/2;
127     for(i=1;i<=m;i++){
128         int x=a[i].x,y=a[i].y;
129         int tmp=LCA(x,y);
130         up+=query(ind[tmp],ind[x],1,ed,rot[x],rot[y],rot[tmp],rot[fa[tmp]]);
131         up+=query(ind[tmp],ind[y],1,ed,rot[x],rot[y],rot[tmp],rot[fa[tmp]]);
132         up-=query(ind[tmp],ind[tmp],1,ed,rot[x],rot[y],rot[tmp],rot[fa[tmp]]);
133         --up;//不包含自身 
134     }
135     for(i=1;i<=m;i++)
136         for(j=i;j<=m && a[j].x==a[i].x && a[j].y==a[i].y;j++){
137             up-=(LL)(j-i)*(j-i-1)/2;
138         }
139     LL tmp=gcd(up,down);
140     up/=tmp;down/=tmp;
141     printf("%lld/%lld\n",up,down);
142     return 0;
143 }

相关文章: