Codeforces Round #548 (Div. 2) C. Edgy Trees

本文介绍了一道算法题目,给定一棵带红黑边的树,求长度为k的所有顶点序列中,至少经过一次黑色边的序列数量。文章提供了问题解析与代码实现,并通过DFS遍历统计每棵全红边子树的顶点数,最终计算出答案。

You are given a tree (a connected undirected graph without cycles) of ?n vertices. Each of the ?1n−1 edges of the tree is colored in either black or red.

You are also given an integer ?k. Consider sequences of ?k vertices. Let's call a sequence [?1,?2,,??][a1,a2,…,ak] good if it satisfies the following criterion:

  • We will walk a path (possibly visiting same edge/vertex multiple times) on the tree, starting from ?1a1 and ending at ??ak.
  • Start at ?1a1, then go to ?2a2 using the shortest path between ?1a1 and ?2a2, then go to ?3a3 in a similar way, and so on, until you travel the shortest path between ??1ak−1 and ??ak.
  • If you walked over at least one black edge during this process, then the sequence is good.

Consider the tree on the picture. If ?=3k=3 then the following sequences are good: [1,4,7][1,4,7], [5,5,3][5,5,3] and [2,3,7][2,3,7]. The following sequences are not good: [1,4,6][1,4,6], [5,5,5][5,5,5], [3,7,3][3,7,3].

There are ??nk sequences of vertices, count how many of them are good. Since this number can be quite large, print it modulo 109+7109+7.

Input

The first line contains two integers ?n and ?k (2?1052≤n≤105, 2?1002≤k≤100), the size of the tree and the length of the vertex sequence.

Each of the next ?1n−1 lines contains three integers ??ui, ??vi and ??xi (1??,???1≤ui,vi≤n, ??{0,1}xi∈{0,1}), where ??ui and ??vi denote the endpoints of the corresponding edge and ??xi is the color of this edge (00 denotes red edge and 11 denotes black edge).

Output

Print the number of good sequences modulo 109+7109+7.

Examples
input
Copy
4 4
1 2 1
2 3 1
3 4 1
output
Copy
252
input
Copy
4 6
1 2 0
1 3 0
1 4 0
output
Copy
0
input
Copy
3 5
1 2 1
2 3 0
output
Copy
210
Note

In the first example, all sequences (4444) of length 4except the following are good:

  • [1,1,1,1][1,1,1,1]
  • [2,2,2,2][2,2,2,2]
  • [3,3,3,3][3,3,3,3]
  • [4,4,4,4][4,4,4,4]

In the second example, all edges are red, hence there aren't any good sequences.

 

 题意:给定一棵树,树上的边有红色和黑色两种颜色。假设一个长度为k的序列<a1,a2,…,ak>,表示从a1开始依次走到序列中的点直到ak,如果在走整个序列的过程中至少经过一次黑色的边,表示这个序列是好的(good sequence)。现在给定一个这个长度k,输出有多少种满足好的序列的个数。

 思路:因为是在树上,当经过一条黑色的边后走访其余的点全都是满足good sequence了。因此统计每一个全是红色边的子树的点数,设为w,仅在这颗子树中互相走访的序列个数为wk。统计出所有的wk最后在nk将它们的和减去就行了。

 代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x&(-x))
#define eps 0.00000001
#define PI acos(-1)
#define ms(x,y) memset(x, y, sizeof(x))
using namespace std;

const ll mod = 1e9+7;
const int maxn = 1e5+7;
struct Edge {
    int to, x;
    Edge(int a=0,int _x=0):to(a), x(_x){}
};
vector <Edge> e[maxn];
int n, k;


int cnt;
int vis[maxn];
void dfs(int u)
{
    vis[u] = 1;
    cnt ++;
    for(int i=0;i<e[u].size();i++)
        if(!e[u][i].x && !vis[e[u][i].to])
            dfs(e[u][i].to);
}

ll qm(ll a, int b)
{
    ll res = 1, base = a;
    while(b)
    {
        if(b&1) res = (res * base) % mod;
        base = (base * base) % mod;
        b >>= 1;
    }
    return res % mod;
}

int main()
{
    int u, v, x;
    scanf("%d%d", &n, &k);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d", &u, &v, &x);
        e[u].push_back(Edge(v, x));
        e[v].push_back(Edge(u, x));
    }
    
    ll tot = 0;
    for(int i=1;i<=n;i++)
    {
        cnt  = 0;
        if(!vis[i])
            dfs(i);
        tot = (tot + qm(cnt, k)) % mod;
    }
    
    printf("%lld\n", (qm(n, k) - tot + mod) % mod);
    
}

 

转载于:https://www.cnblogs.com/HazelNut/p/10583518.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值