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

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);
    
}

 

posted @ 2019-03-23 13:11  HazelNuto  阅读(342)  评论(0编辑  收藏  举报