#pragma GCC optimize "O3,unroll-loops,trapv"
#include <bits/stdc++.h>
#define REP(v, i, j) for (int v = i; v != j; v++)
#define FORI(v) for (auto i : v)
#define FORJ(v) for (auto j : v)
#define OUT(v, a) \
FORI(v) \
cout << i << a;
#define OUTS(v, a, b) \
cout << v.size() << a; \
OUT(v, b)
#define in(a, n) \
REP(i, 0, n) \
cin >> a[i];
#define SORT(v) sort(begin(v), end(v))
#define REV(v) reverse(begin(v), end(v))
#define MEMSET(m) memset(m, -1, sizeof m)
#define pb push_back
#define fi first
#define se second
#define detachIO \
ios_base::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0);
using namespace std;
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
bool operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) {
if(__x.size() != __y.size()) return false;
return std::equal(__x.begin(), __x.end(), __y.begin());
}
typedef pair<long long, long long> pii;
typedef pair<pii, long long> piii;
typedef pair<pii, pii> piiii;
const long long MOD = 1e9+7;
vector<long long> adj[200100];
long long memo1[200100];
bool memo2[200100];
long long memo3[200100][2];
long long parent[200100];
long long memof[200100];
long long override=-1;
long long root=1;
bool overdata=false;
vector<long long> memov[200100];
long long memos[200100];
long long memon[200100][2];
map<pair<pii,bool>,long long> num_winning_memo;
map<pair<pii,bool>,long long> is_winning_memo;
bool has_parent[200100];
bool winning(long long node, long long parent){
if(parent==-1)root=node;
if(node==override)return overdata;
bool ans=false;
memo1[node]=0;
FORI(adj[node]){
if(i!=parent)ans=(not winning(i,node)) or ans,memo1[node]+=!memo1[i];
}
// cerr<<node<<": "<<ans<<'\n';
::parent[node]=parent;
return ans;
}
void update(long long node, long long parent, bool dp){
long long onset=0;
if(!dp)onset++;
FORI(adj[node]){
if(i!=parent && !memo1[i])onset++;
}
memo2[node]=dp;
memof[node]=onset;
FORI(adj[node]){
if(i==parent)continue;
if(!memo1[i])onset--;
update(i,node,onset);
if(!memo1[i])onset++;
}
// long long ans=0;
if(!dp)onset--;
is_winning_memo[{{node,parent},true}]=onset;
if(!dp)onset++;
FORI(adj[node]){
if(i==parent)continue;
if(!memo1[i])onset--;
is_winning_memo[{{node,i},true}]=onset;
if(!memo1[i])onset++;
}
onset++;
if(!dp)onset--;
is_winning_memo[{{node,parent},false}]=onset;
if(!dp)onset++;
FORI(adj[node]){
if(i==parent)continue;
if(!memo1[i])onset--;
is_winning_memo[{{node,i},false}]=onset;
if(!memo1[i])onset++;
}
onset--;
if(is_winning_memo[{{node,parent},true}])num_winning_memo[{{node,parent},true}]++;
FORI(adj[node]){
if(i==parent)continue;
num_winning_memo[{{node,parent},true}]+=num_winning_memo[{{i,node},is_winning_memo[{{node,parent},true}]-(!memo1[i])}];
memon[node][true] += num_winning_memo[{{i,node},true}];
}
if(is_winning_memo[{{node,parent},false}])num_winning_memo[{{node,parent},false}]++;
FORI(adj[node]){
if(i==parent)continue;
num_winning_memo[{{node,parent},false}]+=num_winning_memo[{{i,node},is_winning_memo[{{node,parent},false}]-(!memo1[i])}];
memon[node][false] += num_winning_memo[{{i,node},false}];
}
}
void update2(long long node, long long parent){
set<int> st;
if(!memo2[node])st.insert(parent);
FORI(adj[node]){
if(i!=parent && !memo1[i])st.insert(i);
}
FORI(adj[node]){
if(i==parent)memon[node][true ]+=num_winning_memo[{{parent,node},true }];
if(i==parent)memon[node][false]+=num_winning_memo[{{parent,node},false}];
}
FORI(adj[node]){
if(i!=parent){
st.insert(i);
bool b=st.size();
num_winning_memo[{{node,i},false}] = memon[node][(bool)b] - num_winning_memo[{{i,node},b}];
if(b)num_winning_memo[{{node,i},false}]++;
// if(st.size()==1){
// num_winning_memo[{{node,i},false}] -= num_winning_memo[{{*st.begin(),node},b}];
// num_winning_memo[{{node,i},false}] += num_winning_memo[{{*st.begin(),node},false}];
// }
st.erase(i);
b=st.size();
num_winning_memo[{{node,i},true }] = memon[node][(bool)b] - num_winning_memo[{{i,node},b}];
if(b)num_winning_memo[{{node,i},true }]++;
if(st.size()==1){
num_winning_memo[{{node,i},true }] -= num_winning_memo[{{*st.begin(),node},b}];
num_winning_memo[{{node,i},true }] += num_winning_memo[{{*st.begin(),node},false}];
}
if(!memo1[i])st.insert(i);
update2(i,node);
}
}
}
bool dp(long long node, bool b){
if(node==root)return b;
if(memo3[node][b]!=-1)return memo3[node][b];
if(b == (bool)(memo1[node]))return memo3[node][b]=memo1[root];
if(b && !memo1[node] && memo1[parent[node]]==1){
return memo3[node][b]=dp(parent[node],false);
}
if(!b && memo1[node] && memo1[parent[node]]==0){
return memo3[node][b]=dp(parent[node],true);
}
return memo3[node][b]=dp(parent[node],memo1[parent[node]]);
}
int main(){
detachIO;
long long n;cin>>n;
long long d;cin>>d;
REP(i,1,n){
long long u,v;cin>>u>>v;
adj[u].pb(v);
adj[v].pb(u);
}
long long w=0,l=0;
MEMSET(memof);
winning(1,-1);
update(1,-1,true);
REP(i,1,n+1){
assert(memof[i]!=-1);
// assert(((bool)memof[i])==winning(i,-1));
if(memof[i])w++;
else l++;
}
// cerr<<endl;
// TODO: Matrix expo
piiii mat;
if(d>1){
num_winning_memo.clear();
is_winning_memo.clear();
memset(memon,0,sizeof memon);
memset(memof,0,sizeof memof);
memset(memos,0,sizeof memos);
memset(memo3,0,sizeof memo3);
winning(1,-1);
update(1,-1,true);
update2(1,-1);
REP(j,1,n+1){
mat.se.se += n-1;
mat.fi.se ++;
FORI(adj[j]){
mat.se.se -= num_winning_memo[{{i,j},true}];
mat.fi.se += num_winning_memo[{{i,j},true}];
}
// cerr<<i<<" -> "<<dp(i,true)<<", "<<parent[i]<<", "<<memo1[i]<<'\n';
}
// cerr<<mat.fi.fi<<"\t"<<mat.fi.se<<'\n';
// cerr<<mat.se.fi<<"\t"<<mat.se.se<<'\n';
// REP(j,1,n+1){
// num_winning_memo.clear();
// is_winning_memo.clear();
// memset(memon,0,sizeof memon);
// memset(memof,0,sizeof memof);
// memset(memos,0,sizeof memos);
// memset(memo3,0,sizeof memo3);
// winning(j,-1);
// update(j,-1,true);
// MEMSET(memo3);
// REP(i,1,n+1){
// if(dp(i,true))mat.fi.se--;
// else mat.se.se--;
// // cerr<<i<<" -> "<<dp(i,true)<<", "<<parent[i]<<", "<<memo1[i]<<'\n';
// }
// }
// // cerr<<mat.fi.fi<<"\t"<<mat.fi.se<<'\n';
// // cerr<<mat.se.fi<<"\t"<<mat.se.se<<'\n';
// assert(mat.fi.se==0);
// assert(mat.se.se==0);
// REP(j,1,n+1){
// num_winning_memo.clear();
// is_winning_memo.clear();
// memset(memon,0,sizeof memon);
// memset(memof,0,sizeof memof);
// memset(memos,0,sizeof memos);
// memset(memo3,0,sizeof memo3);
// winning(j,-1);
// update(j,-1,true);
// MEMSET(memo3);
// REP(i,1,n+1){
// if(dp(i,true))mat.fi.se++;
// else mat.se.se++;
// // cerr<<i<<" -> "<<dp(i,true)<<", "<<parent[i]<<", "<<memo1[i]<<'\n';
// }
// }
MEMSET(memof);
num_winning_memo.clear();
is_winning_memo.clear();
memset(memon,0,sizeof memon);
memset(memof,0,sizeof memof);
memset(memos,0,sizeof memos);
memset(memo3,0,sizeof memo3);
winning(1,-1);
update(1,-1,true);
REP(i,1,n+1){
assert(memof[i]!=-1);
if(memof[i])mat.fi.fi+=n;
else mat.se.fi+=n;
}
}
REP(i,0,d-1){
long long w2,l2;
w2=mat.fi.fi * w + mat.fi.se * l;
w2%=MOD;
l2=mat.se.fi * w + mat.se.se * l;
l2%=MOD;
w=w2,l=l2;
}
long long ans=0;
winning(1,-1);
update(1,-1,true);
MEMSET(memo3);
REP(i,1,n+1){
if(dp(i,true))ans+=l;
// cerr<<i<<" -> "<<dp(i,true)<<", "<<parent[i]<<", "<<memo1[i]<<'\n';
}
override=-1;
overdata=true;
const bool r=winning(1,-1);
REP(i,1,n+1){
if(r)ans+=w;
}
cout<<ans%MOD<<'\n';
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |