题解:P10842 【MX-J2-T3】Piggy and Trees
Contingency_Core · · 题解
三倍DFS 三倍快乐(计算点权值)
一眼看上去好像不难?
首先想到的就是DFS计算每个点的权值:\
对于每一个点,讨论这个点作为
于是我们只需要求出每个子树的节点数
再枚举每一个节点作根,对每个根枚举
才交一次就开始红温?
重新观察可以发现我们对情况1用的是这个公式(
如果所有点都在一个根上时间复杂度就是
预处理出
即将结束濒临崩溃?
我们发现,即使经过化简,以上式子还是
预处理出每一个
然而,我们情况2时用的:
还是
现在就可以WA(如果你乱用取模的话)
现在就可以AC了
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdio>
#include <map>
#include <vector>
#include <list>
#include <functional>
#include <stack>
#include <unordered_map>
#include <set>
#include <cctype>
#include <cstring>
#include <bitset>
#include <unordered_set>
#define m(a,b) make_pair(a,b)
#define F first
#define S second
#define us unsigned short
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) (a<b?a:b)
#define XOR(a,b) ((a&&!b)||(!a&&b))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int M=1e9,N=2e5+5;const ll LM=1e18,P=1331,MOD=1e9+7;int YI=1,LING=0;//漫长的头文件,不用看。
ll ans;
int n;
struct zs//子树
{
int g,t;
ll d;
pair<int,int> fan;
inline void add(pair<int,ll> x)
{
d=x.S,t=x.F;
}
inline zs(int cg):g(cg){}
};
struct node
{
bool b;//访问标记(dfs用)
ll d;//子树d值的和
ll dt;//子树d值*t值的和
vector <zs> l;
} a[N];
inline pair<int,ll> dfs0(int x,ll d,int t)
{
node &g=a[x];
g.b=1;
int ts=0;
ll ds=0;
for(auto &i:g.l)
{
if(!a[i.g].b)
{
i.add(dfs0(i.g,d+t+1,t+1));
ds+=i.d;
ts+=i.t;
}
}
g.b=0;
return m(ts+1,ds+ts+1);
}
inline void dfs1(int x,ll d,int t)
{
node &g=a[x];
g.b=1;
g.dt=d*t;
int ts=0;
ll ds=0;
for(auto &i:g.l)
{
if(!a[i.g].b)
{
ds=(ds+i.d);
ts=(ts+i.t);
g.dt=g.dt+i.d*i.t;
}
else
{
i.add(m(t,d));
}
}
for(auto &i:g.l)
{
if(!a[i.g].b)
dfs1(i.g,d+ds+ts+t-i.d-i.t+1,t+ts-i.t+1);
}
g.d=(ds+d);
g.b=0;
}//前两次预处理
inline void dfs2(int x)
{
node &g=a[x];
g.b=1;
int n=g.l.size();
ll cdts=g.dt,cts=(::n-1);
for(int i=0;i<n;i++)
{
zs &cs=g.l[i];
ans=(ans+g.l[i].d*(::n-cs.t-1))%MOD;
cts=(cts-cs.t),cdts=(cdts-cs.t*cs.d);
ans=(ans+cs.t*(cts*(g.d-cs.d)-cdts))%MOD;
}
for(int i=0;i<n;i++)
{
if(!a[g.l[i].g].b)
dfs2(g.l[i].g);
}
g.b=0;
}//最后一次计算ans
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int u,v;
cin>>n;
for(int i=1;i<n;i++)
{
cin>>u>>v;
a[u].l.push_back(zs(v));
a[v].l.push_back(zs(u));
a[u].l.back().fan=m(v,a[v].l.size()-1);
a[v].l.back().fan=m(u,a[u].l.size()-1);
}
dfs0(1,0,0);
dfs1(1,0,0);
dfs2(1);
cout<<ans;
return 0;
}