【点分治练习题·不虚就是要AK】点分治
不虚就是要AK(czyak.c/.cpp/.pas) 2s 128M by zhb
czy很火。因为又有人说他虚了。为了证明他不虚,他决定要在这次比赛AK。
现在他正在和别人玩一个游戏:在一棵树上随机取两个点,如果这两个点的距离是4的倍数,那么算czy赢,否则对方赢。现在czy想知道他能获胜的概率。
*最终输出的概率要求分数的分子和分母的和尽量小且非负数
本题多组数据。对于每组数据:
第一行一个数n,表示树上的节点个数
接下来n-1条边a,b,c描述a到b有一条长度为c的路径
当n=0时表示读入结束
数据组数不超过10。无部分分
输入数据
5
1 2 1
1 3 2
1 4 1
2 5 3
0
输出数据
7/25
数据范围
数据点 |
n的规模 |
数据组数 |
随机生成数据 |
1 |
200 |
1 |
是 |
2 |
200 |
1 |
是 |
3 |
200 |
<=3 |
是 |
4 |
2000 |
<=3 |
是 |
5 |
2000 |
<=3 |
是 |
6 |
2000 |
<=5 |
是 |
7 |
20000 |
<=5 |
否 |
8 |
20000 |
<=5 |
否 |
9 |
20000 |
<=10 |
否 |
10 |
20000 |
<=10 |
否 |
这题其实跟找距离=K的点对有多少个是一样的,我们把距离全部不断mod4就可以了。
然后就是点分治。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<algorithm>
6 using namespace std;
7
8 const int N=20010;
9 int n,len,ans;
10 int v[5],t[5],d[N],first[N],mark[N],size[N];
11 struct node{
12 int x,y,d,next;
13 }a[2*N];
14
15 void ins(int x,int y,int d)
16 {
17 a[++len].x=x;a[len].y=y;a[len].d=d;
18 a[len].next=first[x];first[x]=len;
19 }
20
21 int gcd(int x,int y)
22 {
23 if(y==0) return x;
24 return gcd(y,x%y);
25 }
26
27 void find_root(int x,int fa,int tot,int &root)
28 {
29 size[x]=1;
30 bool bk=1;
31 for(int i=first[x];i;i=a[i].next)
32 {
33 int y=a[i].y;
34 if(y==fa || mark[y]) continue;
35 find_root(y,x,tot,root);
36 size[x]+=size[y];
37 if(2*size[y]>tot) bk=0;
38 }
39 if(bk && 2*(tot-size[x])<=tot) root=x;
40 }
41
42 void DFS(int x,int fa)
43 {
44 int now=((4-d[x])%4+4)%4;
45 ans+=v[now];
46 t[d[x]]++;
47 size[x]=1;
48 for(int i=first[x];i;i=a[i].next)
49 {
50 int y=a[i].y;
51 if(mark[y] || y==fa) continue;
52 d[y]=(d[x]+a[i].d)%4;
53 DFS(y,x);
54 size[x]+=size[y];
55 }
56 }
57
58 void dfs(int x,int tot)
59 {
60 find_root(x,0,tot,x);
61
62 memset(v,0,sizeof(v));
63 mark[x]=1;d[x]=0;v[0]++;
64
65 for(int i=first[x];i;i=a[i].next)
66 {
67 int y=a[i].y;
68 if(mark[y]) continue;
69 d[y]=d[x]+a[i].d;
70 memset(t,0,sizeof(t));
71 DFS(y,x);
72 for(int j=0;j<4;j++) v[j]+=t[j];
73 }
74 for(int i=first[x];i;i=a[i].next)
75 {
76 int y=a[i].y;
77 if(mark[y]) continue;
78 dfs(y,size[y]);
79 }
80 }
81
82 int main()
83 {
84 freopen("a.in","r",stdin);
85 // freopen("czyak.in","r",stdin);
86 // freopen("czyak.out","w",stdout);
87 while(1)
88 {
89 scanf("%d",&n);
90 if(!n) break;
91 ans=0;len=0;
92 memset(mark,0,sizeof(mark));
93 memset(first,0,sizeof(first));
94 for(int i=1;i<n;i++)
95 {
96 int x,y,d;
97 scanf("%d%d%d",&x,&y,&d);
98 d%=4;
99 ins(x,y,d);
100 ins(y,x,d);
101 }
102 // for(int i=1;i<=len;i+=2) printf("%d --> %d %d\n",a[i].x,a[i].y,a[i].d);
103 dfs(1,n);
104 int fz=2*ans+n,fm=n*n;
105 int g=gcd(fz,fm);
106 fz/=g;fm/=g;
107 printf("%d/%d\n",fz,fm);
108 }
109 return 0;
110 }