【点分治练习题·不虚就是要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 }

 

posted @ 2016-11-10 15:49  拦路雨偏似雪花  阅读(584)  评论(0编辑  收藏  举报