首页 > 代码库 > [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 }
[51nod1253]Kundu and Tree
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。