无向图中边权是2019倍数的路径数;
我这里面有一篇是求边权是3的倍数,见另外一篇文章,点这儿(【luogu P2634】聪聪可可)
。
思路:
思路:dp[i][j]表示点 i 的子节点到点 i 的距离mod 2019 = j的路径个数。设一点为u,其子节点为v,u、v间的边权值为w。
转移方程为:dp[u][j]+=dp[v][(j-w+2019)%2019];
而结果ans += dp[u][j] * dp[u][(2019-j-weihgt) % 2019];
就是和为2019. (j+2019)—到u点的距离,
# include<bits/stdc++.h>
using namespace std;
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;
vector <int>mp[20005];
vector <int>w[20005];
int dp[20005][2020];
ll ans=0;
void dfs(int fa, int now)
{
dp[now][0] = 1;
for(int i = 0; i < mp[now].size(); ++i)
{
int next = mp[now][i];
int weight = w[now][i];
if(next == fa) continue;
dfs(now, next);
for(int j = 0; j < 2019; ++j)
{
ans += dp[now][j] * dp[next][(2019-weight-j+2019) % 2019];
}
for(int j = 0; j < 2019; ++j)
{
dp[now][j] += dp[next][(j-weight+2019)%2019];
}
}
}
int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i = 1; i <= n; ++i)
{
mp[i].clear();
w[i].clear();
for(int j = 0; j <= 2019; j++)
{
dp[i][j] = 0;
}
}
for(int i = 1; i < n; ++i)
{
int a, b, c;
cin>>a>>b>>c;
mp[a].push_back(b);
mp[b].push_back(a);
w[a].push_back(c);
w[b].push_back(c);
}
ans = 0;
dfs(0,1);
cout<<ans<<endl;
}
return 0;
}