首页 > 代码库 > [51nod1253]Kundu and Tree

[51nod1253]Kundu and Tree

  树包含N个点和N-1条边。树的边有2中颜色红色(‘r‘)和黑色(‘b‘)。给出这N-1条边的颜色,求有多少节点的三元组(a,b,c)满足:节点a到节点b、节点b到节点c、节点c到节点a的路径上,每条路径都至少有一条边是红色的。
  注意(a,b,c), (b,a,c)以及所有其他排列被认为是相同的三元组。输出结果对1000000007取余的结果。

 Input
  第1行:1个数N(1 <= N <= 50000)
  第2 - N行:每行2个数加一个颜色,表示边的起始点和结束的以及颜色。
 Output
  输出1个数,对应符合条件的3元组的数量。

 

 

  奇特的思路。。黑边没有什么用...就把黑边相连的合成一个联通块。

  只要选择的三个点在不同的联通块内就合法了...

  答案就变成 随便选三个点的方案数 - 三个点在同个联通块内的方案数 - 两个点在同个联通块内的方案数

技术分享
 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 #include<cstdlib> 8 #define ll long long 9 #define ull unsigned long long10 #define ui unsigned int11 //#define d double12 #define ld long double13 const int maxn=50023,modd=1000000007;14 int c[maxn][4],fa[maxn],sz[maxn];15 int i,j,k,n,m;16 17 int ra,fh;char rx;18 inline int read(){19     rx=getchar(),ra=0,fh=1;20     while(rx<0&&rx!=-)rx=getchar();21     if(rx==-)fh=-1,rx=getchar();22     while(rx>=0)ra=ra*10+rx-48,rx=getchar();return ra*fh;23 }24 inline int getfa(int x){return fa[x]!=x?fa[x]=getfa(fa[x]):x;}25 inline void MOD(int &x){if(x>=modd)x-=modd;}26 inline void UPD(int &x){if(x<0)x+=modd;}27 int main(){28     n=read();29     c[0][0]=1;register int i,j;30     for(i=1;i<=n;i++){31         c[i][0]=sz[i]=1,fa[i]=i;32         for(j=1;j<=3;j++)MOD(c[i][j]=c[i-1][j-1]+c[i-1][j]);//,printf(" %d %d   c:%d\n",i,j,c[i][j]);33     }34     int x,y;35     for(i=1;i<n;i++){36         x=read(),y=read();37         if(getchar()==b)x=getfa(x),y=getfa(y),fa[x]=y,sz[y]+=sz[x];38     }39     int ans=c[n][3];40     for(i=1;i<=n;i++)if(fa[i]==i)41         UPD(ans-=(c[sz[i]][3]+1ll*(n-sz[i])*c[sz[i]][2])%modd);42     printf("%d\n",ans);43 }
View Code

 

[51nod1253]Kundu and Tree