CF 1139C Edgy Trees

版权声明:没什么好说的,版权声明呢 https://blog.csdn.net/weixin_43741224/article/details/88867224

这个题目太长了,我就放个连接算了: http://codeforces.com/problemset/problem/1139/C

题目分析

     这个题把题意读懂了就好弄了,本以为是最短路的,但应该是求连通块的。

     要在一个有n个结点的树上找一个长度为k,且由结点组成的序列[a1,a2....ak],代表行路的路线a1- a2 - .... - ak , 任意两个结点之间需要用最短的距离走到(还以为要求多元最短路呢),如果在这个行走过程中经过了一条黑色边,那么这个序列就满足题目的条件,问你一共有多少这样的序列。

     由于每一个序列中的元素可以重复出现,也就是说任意的ai都有n个取值,所以总序列个数为n^k个,我们应该可以想到,除去没有经过黑色边的序列,剩余的序列都可以满足条件,那我们要如何让一个序列不会经过黑色边呢?

     如果我们删除了所有的黑色边,由于边的总数为n-1条,那么可能出现多个由红色边相连的连通块,那么由这个连通块内的结点组成的长度为k的序列,必然不满足条件,那我们将所有的这样的连通块全部找出,就得到了所有的不经过黑色的边的序列,最后用总序列数n^k减去这些没有经过黑色边的连通块,就是我们要求的答案了。

      然后注意一些细节问题,由于我们不断地求a^k,所以添加了一个快速幂算法来加速;然后还需要用dfs求连通块的结点数.

代码区

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include <vector>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int Max = 1e6 + 10;
const int mod = 1e9 + 7;

vector<int>v[Max];		//记录红色色边
bool vis[Max];			//vis[x]记录点是否已经被访问

ll pow_fast(ll a, ll k)
{
	ll ans = 1;
	while (k != 0)
	{
		if (k & 1 != 0)ans = (ans*a) % mod;
		a = a * a%mod;
		k >>= 1;
	}
	return ans;
}

void dfs(int s,ll &ans)
{
	vis[s] = true;
	ans++;
	for (int i = 0;i < v[s].size();i++)
	{
		int e = v[s][i];
		if (vis[e])continue;
		dfs(e,ans);
	}
}

int main()
{
	ll n, k;

	while (scanf("%I64d%I64d", &n, &k) != EOF)
	{
		for(int i = 1; i <= n ; i++)
		{
			v[i].clear();
		}
		memset(vis, false, sizeof(vis));
		for (int i = 1; i < n;i++)
		{
			int s, e, m;
			scanf("%d%d%d", &s, &e, &m);
			if (m)continue;	                                        //黑边不记录,这样我们就将所有的点由红边连接,导致出现多个由红边连接的连通块
			v[s].push_back(e);
			v[e].push_back(s);
		}
		ll ans = pow_fast(n, k);		                        //总共走k个点,每个结点都是n个结点中的任意一个,故总数为n^k
		for (int i = 1; i <= n; i++)
		{
			if (!vis[i])				                //没有走过,也就是一个新的连通块
			{
				ll num = 0;				        //记录连通在一起的红色道路
				dfs(i,num);				        //获取纯红边连接的结点
				ans = (ans - pow_fast(num, k) + mod) % mod;	//减去全部由红色边组成的答案
															//也就是用num个点,走动k次
			}
		}
		printf("%I64d\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43741224/article/details/88867224