Topic link: https: //ac.nowcoder.com/acm/contest/1099/I
Partition point, calculating the number of paths when the first distance from each point to the root module 2019, can be calculated when the O (n) determined number, for special handling after molding 2019 to 0.
#include<iostream> #include<algorithm> #include<vector> using namespace std; #define maxn 100005 #define inf 0x3f3f3f3f int n,k,cnt,root,ans,maxx,head[maxn],size[maxn],son[maxn],vis[maxn],num[maxn]; struct edge{ int to,next,val; }e[maxn]; vector<int>dis; void add(int u,int v,int val) { e[++cnt].to=v; e[cnt].next=head[u]; e[cnt].val=val; head[u]=cnt; } void dfs_size(int u,int fa)//求各点子树大小 { size[u]=1;son[u]=0; for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v!=fa&&!vis[v]) { dfs_size(v,u); size[u]+=size[v]; son[u]=max(son[u],size[v]); } } } void dfs_root(int N,int u,int fa)//求重心 { son[u]=max(son[u],N-size[u]); if(maxx>son[u]) { root=u; maxx=son[u]; } for(int i=head[u];i;i=e[i].next) { int v=e[i].to; if(v!=fa&&!vis[v]) dfs_root(N,v,u); } } void dfs_dis(int U,intFA, int Val) // Determine all points to the root of the distance { Val % = 2019 ; NUM [Val] ++ ; // dis.push_back (Val); for ( int I = head [U]; I; I = E [I] .next) { int V = E [I] .to; IF ! (V FA = &&! VIS [V]) dfs_dis (V, U, Val + E [I] .val); } } int CAL ( int U, int Val) // calculate k less number of paths { for ( int I = 0;i<=2019;i++) num[i]=0; //dis.clear(); dfs_dis(u,0,val); //sort(dis.begin(),dis.end()); int l=0,r=dis.size()-1,ret=0; for(int i=1;i<2019;i++)//two-pointer { if(num[i]&&num[2019-i])ret+=num[i]*num[2019-i]; } ret/=2; RET + = NUM [ 0 ] * (NUM [ 0 ] - . 1 ) / 2 ; return RET; } void DFS ( int U) { dfs_size (U, 0 ); Maxx = INF; dfs_root (size [U], U, 0 ); ANS + = CAL (the root, 0 ); // this case paths is calculated without including the number of paths through the roots, the latter need to subtract this number of paths VIS [the root] = . 1 ; // will roo selected and traversed t marked, which prevents process after the partition for ( int I = head [the root]; I; I = E [I] .next) { intE = V [I] .to, Val = E [I] .val; IF (! VIS [V]) { ANS - CAL = (V, Val); // subtree plus all sides dis (u, v ) after the number of paths satisfying the number of paths is subtracted DFS (V); // recursive partition } } } int main () { the while (Scanf ( " % D " !, & n-) = the EOF) { int U, V, Val; for ( int I = . 1 ; I <= n-; I ++ ) head [I] = VIS [I] = 0 ; CNT = ANS = 0; for(int i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&val); add(u,v,val); add(v,u,val); } dfs(1); printf("%d\n",ans); } return 0; }