最近学了下点分治
说道点分治就得先说到树的重心
树的重心的定义是:最大的子树最小的节点。
为什么要找树的重心呢
因为找到树的重心把他变成根以后,最大的子树的大小不超过n/2,否则如果超过n/2将该子树的根作为重心将会更优。
这样可以保证递归的层数不超过logn层,同时保证每个点最多被计算logn次。
那么如何找重心呢
根据定义,我们不妨维护一下两个数组sz[]和mx[]表示以r为根的子树大小和无根树中的最大子树大小,那么mx最小的那个节点就是重心。
有两种写法 一种是
void getroot(int x,int fa) { son[x]=1;f[x]=0; for(int i=head[x];i;i=e[i].next) { if(e[i].to==fa||vis[e[i].to])continue; getroot(e[i].to,x); son[x]+=son[e[i].to]; f[x]=max(f[x],son[e[i].to]); } f[x]=max(f[x],sum-son[x]); if(f[x]<f[root])root=x; }
另一种写法是用两个函数
void dfs_size(int x,int fa) { sz[x]=1; mx[x]=0; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_size(p->to,x); sz[x] += sz[p->to]; maxit(mx[x],sz[p->to]); } } int root=0; void dfs_root(int r,int x,int fa) { maxit(mx[x],sz[r]-sz[x]); if(mx[x]<mx[root]) root=x; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_root(r,p->to,x); } }
我采用的后者,因为太弱了第一种一开始没看懂。
我一直觉得只用dfs一次就可以把每个子树的重心找到,后来发现每一棵子树都要找一次orz感觉复杂度一下就上去了
然后有两道找树的重心的题
poj1655

1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cstring> 6 7 using namespace std; 8 9 const int Maxn=20000+10,INF=0x7fffffff; 10 11 struct Edge{ 12 int to; 13 Edge*next; 14 Edge(int to=0,Edge* next=0):to(to),next(next){} 15 }pool[Maxn*2],*fir[Maxn],*pis=pool; 16 17 void AddEdge(int from,int to){ 18 *pis=Edge(to,fir[from]);fir[from]=pis++; 19 *pis=Edge(from,fir[to]);fir[to]=pis++; 20 } 21 22 int sz[Maxn],mx[Maxn]; 23 void dfs_size(int x,int fa) { 24 sz[x]=1; 25 mx[x]=0; 26 for(Edge*p=fir[x];p;p=p->next) { 27 if(p->to==fa) continue; 28 dfs_size(p->to,x); 29 sz[x] += sz[p->to]; 30 mx[x]=max(mx[x],sz[p->to]); 31 } 32 } 33 34 int root; 35 36 void dfs_root(int r,int x,int fa) { 37 mx[x]=max(mx[x],sz[r]-sz[x]); 38 if(mx[root]>mx[x]) root=x; 39 for(Edge*p=fir[x];p;p=p->next) { 40 if(p->to==fa) continue; 41 dfs_root(r,p->to,x); 42 } 43 } 44 45 int n; 46 void init() { 47 root=0; 48 mx[0]=INF; 49 pis=pool; 50 memset(fir,0,sizeof fir); 51 for(int i=1;i<n;i++) { 52 int u,v; 53 scanf("%d%d",&u,&v); 54 AddEdge(u,v); 55 } 56 } 57 58 int main() { 59 #ifdef DEBUG 60 freopen("in.txt","r",stdin); 61 freopen("out.txt","w",stdout); 62 #endif 63 64 int T; 65 for(scanf("%d",&T);T--;) { 66 scanf("%d",&n); 67 init(); 68 dfs_size(1,0); 69 dfs_root(1,1,0); 70 printf("%d %d ",root,mx[root]); 71 } 72 73 return 0; 74 }
poj3170

1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cstring> 6 7 using namespace std; 8 9 const int Maxn=50000+10,INF=0x7fffffff; 10 11 struct Edge{ 12 int to; 13 Edge*next; 14 Edge(int to=0,Edge* next=0):to(to),next(next){} 15 }pool[Maxn*2],*fir[Maxn],*pis=pool; 16 17 void AddEdge(int from,int to){ 18 *pis=Edge(to,fir[from]);fir[from]=pis++; 19 *pis=Edge(from,fir[to]);fir[to]=pis++; 20 } 21 22 int sz[Maxn],mx[Maxn]; 23 void dfs_size(int x,int fa) { 24 sz[x]=1; 25 mx[x]=0; 26 for(Edge*p=fir[x];p;p=p->next) { 27 if(p->to==fa) continue; 28 dfs_size(p->to,x); 29 sz[x] += sz[p->to]; 30 mx[x]=max(mx[x],sz[p->to]); 31 } 32 } 33 34 int root; 35 int ans[Maxn],tot; 36 37 void dfs_root(int r,int x,int fa) { 38 mx[x]=max(mx[x],sz[r]-sz[x]); 39 if(mx[root]>mx[x]) ans[tot=1]=root=x; 40 else if(mx[root]==mx[x]) ans[++tot]=x; 41 for(Edge*p=fir[x];p;p=p->next) { 42 if(p->to==fa) continue; 43 dfs_root(r,p->to,x); 44 } 45 } 46 47 int n; 48 void init() { 49 root=0; 50 mx[0]=INF; 51 pis=pool; 52 memset(fir,0,sizeof fir); 53 for(int i=1;i<n;i++) { 54 int u,v; 55 scanf("%d%d",&u,&v); 56 AddEdge(u,v); 57 } 58 } 59 60 int main() { 61 #ifdef DEBUG 62 freopen("in.txt","r",stdin); 63 freopen("out.txt","w",stdout); 64 #endif 65 66 for(;~scanf("%d",&n);) { 67 init(); 68 dfs_size(1,0); 69 dfs_root(1,1,0); 70 sort(ans+1,ans+tot+1); 71 for(int i=1;i<=tot;i++) { 72 printf("%d%c",ans[i],i==n?' ':' '); 73 } 74 } 75 76 return 0; 77 }
之后做了几道hzwer上的点分治,贴下代码QuQ
bzoj2152

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> using namespace std; const int Maxn=20005,INF=0x7fffffff; struct Edge{ int to,v; Edge*next; Edge(int to=0,int v=0,Edge*next=NULL):to(to),v(v),next(next){ } }pool[Maxn*2],*fir[Maxn],*pis; void AddEdge(int from,int to,int v){ *pis=Edge(to,v,fir[from]);fir[from]=pis++; *pis=Edge(from,v,fir[to]);fir[to]=pis++; } int sz[Maxn],mx[Maxn]; int vis[Maxn],clk; void dfs_size(int x,int fa) { sz[x]=1; mx[x]=0; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_size(p->to,x); sz[x] += sz[p->to]; mx[x] = max(mx[x],sz[p->to]); } } int root=0; void dfs_root(int r,int x,int fa) { mx[x] = max(mx[x],sz[r]-sz[x]); if(mx[root]>mx[x]) root=x; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_root(r,p->to,x); } } int num[3]; void dfs_dis(int x,int d,int fa) { num[d]++; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_dis(p->to,(d+p->v)%3,x); } } int k; int calc(int x,int d) { int ret=0; memset(num,0,sizeof num); dfs_dis(x,d,0); ret += num[0]*(num[0]-1)/2; ret += num[1]*num[2]; return ret; } int ans; void dfs(int x) { dfs_size(x,0); root=0; dfs_root(x,x,0); vis[root]=clk; ans += calc(root,0); for(Edge*p=fir[root];p;p=p->next) { if(vis[p->to]==clk) continue; ans -= calc(p->to,p->v); dfs(p->to); } } int n; void init() { memset(mx,0,sizeof mx); mx[0]=INF; ans=0; ++clk; memset(fir,0,sizeof fir); pis=pool; int u,v,w; for(int i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&w); AddEdge(u,v,w%3); } } int gcd(int a,int b) { if(b==0) return a; return gcd(b,a%b); } int main(){ #ifdef DEBUG freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif for(;scanf("%d",&n)==1 && n;) { init(); dfs(1); int a=ans*2+n,b=n*n; int g=gcd(a,b); printf("%d/%d ",a/g,b/g); } return 0; }
bzoj3697

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> using namespace std; typedef long long ll; const int Maxn=100005,INF=0x3f3f3f3f; struct Edge{ int to,v; Edge*next; Edge(int to=0,int v=0,Edge*next=NULL):to(to),v(v),next(next){ } }pool[Maxn*2],*fir[Maxn],*pis; void AddEdge(int from,int to,int v){ *pis=Edge(to,v,fir[from]);fir[from]=pis++; *pis=Edge(from,v,fir[to]);fir[to]=pis++; } int sz[Maxn],mx[Maxn]; int vis[Maxn],clk; void dfs_size(int x,int fa) { sz[x]=1; mx[x]=0; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_size(p->to,x); sz[x] += sz[p->to]; mx[x] = max(mx[x],sz[p->to]); } } int root=0; void dfs_root(int r,int x,int fa) { mx[x] = max(mx[x],sz[r]-sz[x]); if(mx[root]>mx[x]) root=x; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_root(r,p->to,x); } } int n; int f[Maxn*2+10][2]; int g[Maxn*2+10][2]; int t[Maxn*2+10]; int max_deep; #define f(a,b) f[a+n][b] #define g(a,b) g[a+n][b] #define t(a) t[a+n] void dfs_dis(int x,int d,int fa) { max_deep=max(max_deep,abs(d)); if(t(d)++) g(d,1)++; else g(d,0)++; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_dis(p->to,d+p->v,x); } t(d)--; } int k; ll ans; void dfs(int x) { int mx=0; dfs_size(x,0); root=0; dfs_root(x,x,0); vis[root]=clk; f(0,0)=1; for(Edge*p=fir[root];p;p=p->next) { if(vis[p->to]==clk) continue; max_deep=0; dfs_dis(p->to,p->v,root); mx=max(max_deep,mx); ans += 1ll*(f(0,0)-1)*g(0,0); for(int i = -max_deep;i <= max_deep;i++) { ans += 1ll*f(i,0)*g(-i,1) + f(i,1)*g(-i,0) + f(i,1)*g(-i,1); } for(int i = -max_deep;i <= max_deep;i++) { f(i,0) += g(i,0); f(i,1) += g(i,1); g(i,0) = g(i,1) = 0; } } for(int i=-mx;i<=mx;i++) f(i,0)=f(i,1)=0; for(Edge*p=fir[root];p;p=p->next) { if(vis[p->to]!=clk) dfs(p->to); } } void init() { max_deep=0; memset(mx,0,sizeof mx); mx[0]=INF; ans=0; ++clk; memset(fir,0,sizeof fir); pis=pool; int u,v,w; for(int i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&w); AddEdge(u,v,w==1?1:-1); } } int main(){ #ifdef DEBUG freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif for(;scanf("%d",&n)==1;) { init(); dfs(1); cout<<ans<<endl; } return 0; }
bzoj1758

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> using namespace std; typedef long long ll; const int Maxn=100005,INF=0x3f3f3f3f; const double eps=1e-7; int U,L; struct Edge{ int to,v; Edge*next; Edge(int to=0,int v=0,Edge*next=NULL):to(to),v(v),next(next){ } }pool[Maxn*2],*fir[Maxn],*pis; void AddEdge(int from,int to,int v){ *pis=Edge(to,v,fir[from]);fir[from]=pis++; *pis=Edge(from,v,fir[to]);fir[to]=pis++; } template<typename Q> void maxit(Q&x,const Q&y) { if(x<y) x=y; } int sz[Maxn],mx[Maxn]; int vis[Maxn],clk=0; void dfs_size(int x,int fa) { sz[x]=1; mx[x]=0; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_size(p->to,x); sz[x] += sz[p->to]; maxit(mx[x],sz[p->to]); } } int root=0; void dfs_root(int r,int x,int fa) { maxit(mx[x],sz[r]-sz[x]); if(mx[x]<mx[root]) root=x; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_root(r,p->to,x); } } int dep[Maxn],fa[Maxn]; double dis[Maxn],M,ans=0,lim; double f[Maxn]; bool check(int x) { int up=0; for(Edge*p=fir[x];p;p=p->next) { if(vis[p->to]==clk) continue; // if(f[0]!=0) exit(1); static int q[Maxn],ql,qr; ql=qr=0; fa[x]=0; dis[x]=dep[x]=0; q[++qr]=p->to; fa[p->to]=x; dep[p->to]=1; dis[p->to]=p->v-M; for(int u;ql<qr;) { u=q[++ql]; for(Edge*p=fir[u];p;p=p->next) { if(p->to!=fa[u] && vis[p->to]!=clk) { q[++qr] = p->to; fa[p->to]=u; dep[p->to]=dep[u]+1; dis[p->to]=dis[u]+p->v-M; } } } for(int i=up+1;i<=dep[q[qr]];i++) f[i]= -INF; static int mq[Maxn],ml,mr; ml=mr=0;int now=up; for(int i=1;i<=qr;i++) { int x=q[i]; for(;dep[x]+now>=L&&now>=0;now--) { for(;ml<mr && f[mq[mr]] < f[now];mr--); mq[++mr] = now; } for(;dep[x]+mq[ml+1]>U && ml<mr;ml++); if(ml<mr && f[mq[ml+1]] + dis[x]>=-eps) return 1; } for(int i=1;i<=qr;i++) { maxit(f[dep[q[i]]],dis[q[i]]); } maxit(up,dep[q[qr]]); } return 0; } void dfs(int x) { dfs_size(x,0); dfs_root(x,x,root=0); vis[root]=clk; double l=ans,r=lim; for(;r-l>eps;) { M=l+(r-l)/2; if(check(root)) l=M; else r=M; } ans=l; for(Edge*p=fir[root];p;p=p->next) { if(!vis[p->to]) dfs(p->to); } } int n; void init() { mx[0]=INF; ++clk; memset(fir,0,sizeof fir); pis=pool; scanf("%d%d%d",&n,&L,&U); for(int i=1;i<n;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); AddEdge(u,v,w); maxit(lim,(double)w); } } int main(){ #ifdef DEBUG freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif init(); dfs(1); printf("%.3lf ",ans); return 0; }
bzoj3784

1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 #include<queue> 7 8 using namespace std; 9 10 const int Maxn=50010,logn=21; 11 const int nlogn=800000; 12 const int INF=0x3f3f3f3f; 13 struct Edge{ 14 int to,v; 15 Edge*next; 16 Edge(int to=0,Edge*next=0,int v=0):to(to),v(v),next(next){} 17 }pool[Maxn*2],*pis=pool,*fir[Maxn]; 18 19 void AddEdge(int from,int to,int v) { 20 *pis=Edge(to,fir[from],v);fir[from]=pis++; 21 *pis=Edge(from,fir[to],v);fir[to]=pis++; 22 } 23 24 template<typename Q>void maxit(Q&x,const Q&y) { 25 if(x<y) x=y; 26 } 27 int sz[Maxn],mx[Maxn]; 28 bool vis[Maxn]; 29 void dfs_size(int x,int fa) { 30 sz[x]=1; 31 mx[x]=0; 32 for(Edge*p=fir[x];p;p=p->next) { 33 if(vis[p->to] || p->to==fa) continue; 34 dfs_size(p->to,x); 35 sz[x] += sz[p->to]; 36 maxit(mx[x],sz[p->to]); 37 } 38 } 39 40 int root=0; 41 void dfs_root(int r,int x,int fa) { 42 maxit(mx[x],sz[r]-sz[x]); 43 if(mx[x]<mx[root]) root=x; 44 for(Edge*p=fir[x];p;p=p->next) { 45 if(vis[p->to] || p->to==fa) continue; 46 dfs_root(r,p->to,x); 47 } 48 } 49 50 int tot; 51 struct Data2 { 52 int v,pos; 53 Data2(int v=0,int pos=0):v(v),pos(pos) {} 54 Data2 operator + (const Data2&rhs) const { 55 return v>rhs.v?*this:rhs; 56 } 57 }st[nlogn][logn]; 58 59 void dfs_dis(int x,int d,int fa) { 60 ++tot; 61 st[tot][0] = Data2(d,tot); 62 for(Edge*p=fir[x];p;p=p->next) { 63 if(vis[p->to] || p->to==fa) continue; 64 dfs_dis(p->to,d+p->v,x); 65 } 66 } 67 68 int L[nlogn],R[nlogn]; 69 70 struct Data { 71 int id,l,r,v,pos; 72 bool operator < (const Data& rhs) const { 73 return v<rhs.v; 74 } 75 Data(int id,int l,int r,int v,int pos):id(id),l(l),r(r),v(v),pos(pos) {} 76 Data() {} 77 }; 78 79 priority_queue<Data> q; 80 81 void st_init() { 82 for(int i=0;i<=tot;i++) { 83 for(int j=1;(i+(1<<(j-1)))<=tot;j++) { 84 st[i][j] = st[i][j-1] + st[i+(1<<(j-1))][j-1]; 85 } 86 } 87 } 88 89 Data2 st_query(int l,int r) { 90 int k=0; 91 while( ( 1<<(k+1) ) <=r-l+1)k++;//如果2^(k+1)<=R-L+1,则k还可以+1 92 return st[l][k]+st[r-(1<<k)+1][k]; 93 } 94 95 void dfs(int x) { 96 dfs_size(x,0); 97 dfs_root(x,x,root=0); 98 vis[x=root]=1; 99 100 int s=++tot; 101 st[tot][0]=Data2(0,tot); 102 for(Edge*p=fir[x];p;p=p->next) { 103 if(vis[p->to]) continue; 104 int t=tot; 105 dfs_dis(p->to,p->v,x); 106 for(int i=t+1;i<=tot;i++) { 107 L[i]=s; 108 R[i]=t; 109 } 110 } 111 for(Edge*p=fir[x];p;p=p->next) { 112 if(!vis[p->to]) dfs(p->to); 113 } 114 } 115 116 int n,m; 117 118 void init() { 119 mx[0]=INF; 120 scanf("%d%d",&n,&m); 121 for(int i=1;i<n;i++) { 122 int u,v,w; 123 scanf("%d%d%d",&u,&v,&w); 124 AddEdge(u,v,w); 125 } 126 } 127 128 //#define dout printf 129 void work() { 130 dfs(1); 131 st_init(); 132 133 /* 134 dout("tot=%d ",tot); 135 for(int i=1;i<=tot;i++) { 136 dout("(%d,%d,%d) ",st[i][0].v,L[i],R[i]); 137 } 138 dout("------------------ "); 139 for(int i=1;i<=tot;i++) { 140 for(int j=0;(1<<j)<=tot;j++) { 141 dout("st[%d][%d]=(%d,%d)",i,j,st[i][j].v,st[i][j].pos); 142 } 143 dout(" "); 144 }*/ 145 146 for(int i=1;i<=tot;i++) { 147 // if(L[i]==R[i] && L[i]==0) continue; 148 Data2 tmp=st_query(L[i],R[i]); 149 q.push(Data(i, L[i],R[i], tmp.v+st[i][0].v, tmp.pos)); 150 } 151 for(Data s;m--;) { 152 s=q.top();q.pop(); 153 printf("%d ",s.v); 154 if(s.l!=s.pos) { 155 Data2 t=st_query(s.l,s.pos-1); 156 q.push(Data(s.id, s.l, s.pos-1, t.v+st[s.id][0].v, t.pos)); 157 } 158 if(s.r!=s.pos) { 159 Data2 t=st_query(s.pos+1,s.r); 160 q.push(Data(s.id, s.pos+1, s.r, t.v+st[s.id][0].v, t.pos)); 161 } 162 } 163 } 164 165 166 int main() { 167 #ifdef DEBUG 168 freopen("in.txt","r",stdin); 169 // freopen("out.txt","w",stdout); 170 #endif 171 172 init(); 173 work(); 174 175 return 0; 176 }
bzoj4016

1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 #include<vector> 7 #include<queue> 8 9 using namespace std; 10 11 const int Maxn=30000+10,Maxm=60000+10,INF=0x3f3f3f3f; 12 typedef pair<int,int> pii; 13 vector<pii>e[Maxn]; 14 15 void AddEdge(int from,int to,int w) { 16 e[from].push_back(make_pair(to,w)); 17 e[to].push_back(make_pair(from,w)); 18 } 19 struct Edge{ 20 int to; 21 Edge*next; 22 int w; 23 Edge(int to=0,Edge*next=0,int w=0):to(to),next(next),w(w) {} 24 }pool[Maxn*2+Maxm*2],*pis=pool,*fir0[Maxn],*fir[Maxn]; 25 26 void Add(Edge* fir[],int from,int to,int w) { 27 *pis=Edge(to,fir[from],w);fir[from]=pis++; 28 // *pis=Edge(from,fir[to],w);fir[to]=pis++; 29 } 30 31 priority_queue<pii,vector<pii>,greater<pii> > q; 32 int d[Maxn]; 33 bool vis[Maxn]; 34 void Dijkstra() { 35 memset(d,0x3f,sizeof d); 36 q.push(make_pair(0,1)); 37 d[1]=0; 38 for(pii tmp;!q.empty();) { 39 tmp=q.top();q.pop(); 40 int x=tmp.second; 41 if(vis[x]) continue; 42 vis[x]=1; 43 for(Edge*p=fir0[x];p;p=p->next) { 44 if(d[x]+p->w < d[p->to]) { 45 d[p->to] = d[x]+p->w; 46 q.push(make_pair(d[p->to],p->to)); 47 } 48 } 49 } 50 } 51 52 void dfs_path(int x) { 53 vis[x]=1; 54 for(Edge*p=fir0[x];p;p=p->next) { 55 if(!vis[p->to] && d[x]+p->w==d[p->to]) { 56 Add(fir,x,p->to,p->w); 57 Add(fir,p->to,x,p->w); 58 dfs_path(p->to); 59 } 60 } 61 } 62 63 64 int sz[Maxn],mx[Maxn]; 65 int root=0; 66 67 template<typename Q> void maxit(Q&x,Q y) { 68 if(x<y) x=y; 69 } 70 71 void dfs_size(int x,int fa) { 72 sz[x]=1; 73 mx[x]=0; 74 for(Edge*p=fir[x];p;p=p->next) { 75 if(vis[p->to] || p->to==fa) continue; 76 dfs_size(p->to,x); 77 sz[x] += sz[p->to]; 78 maxit(mx[x],sz[p->to]); 79 } 80 } 81 82 void dfs_root(int r,int x,int fa) { 83 maxit(mx[x],sz[r]-sz[x]); 84 if(mx[x]<mx[root]) root=x; 85 for(Edge*p=fir[x];p;p=p->next) { 86 if(p->to==fa || vis[p->to]) continue; 87 dfs_root(r,p->to,x); 88 } 89 } 90 91 int max_deep,md; 92 int f[Maxn][2],g[Maxn][2];//[i][0] i条的最大长度 [1]方案数 93 int K; 94 void dfs_dis(int x,int dep,int d,int fa) { 95 if(dep>K) return; 96 maxit(max_deep,dep); 97 maxit(md,dep); 98 if(g[dep][0]<d) g[dep][0]=d, g[dep][1]=1; 99 else if(g[dep][0]==d) g[dep][1]++; 100 101 for(Edge*p=fir[x];p;p=p->next) { 102 if(p->to==fa || vis[p->to]) continue; 103 dfs_dis(p->to,dep+1,d+p->w,x); 104 } 105 } 106 107 int ans1=0,ans2; 108 void dfs(int x) { 109 dfs_size(x,0); 110 dfs_root(x,x,root=0); 111 vis[x=root]=1; 112 113 max_deep=0; 114 g[0][0]=f[0][0]=0; 115 g[0][1]=f[0][1]=1; 116 117 for(Edge*p=fir[x];p;p=p->next) { 118 if(vis[p->to]) continue; 119 md=0; 120 dfs_dis(p->to,1,p->w,x); 121 122 for(int i=1;i<=md;i++) { 123 if(g[i][0] + f[K-i][0]>ans1) 124 ans1=g[i][0] + f[K-i][0],ans2=0; 125 if(g[i][0] + f[K-i][0]==ans1) 126 ans2 += g[i][1] * f[K-i][1]; 127 } 128 for(int i=1;i<=md;i++) { 129 if(f[i][0]<g[i][0]) f[i][0]=g[i][0], f[i][1]=0; 130 if(f[i][0]==g[i][0]) f[i][1] += g[i][1]; 131 g[i][0]=-INF; 132 } 133 } 134 for(int i=1;i<=max_deep;i++) f[i][0]=0; 135 for(Edge*p=fir[x];p;p=p->next) { 136 if(!vis[p->to]) dfs(p->to); 137 } 138 } 139 140 int n,m; 141 142 void init() { 143 scanf("%d%d%d",&n,&m,&K); K--; 144 int u,v,w; 145 for(int i=1;i<=m;i++) { 146 scanf("%d%d%d",&u,&v,&w); 147 AddEdge(u,v,w); 148 } 149 for(int i=1;i<=n;i++) { 150 sort(e[i].begin(),e[i].end()); 151 for(int j=e[i].size()-1;j>=0;j--) { 152 Add(fir0, i, e[i][j].first, e[i][j].second); 153 } 154 } 155 mx[0]=INF; 156 // for(int i=0;i<Maxn;i++) f[i][0]=g[i][0]=-INF; 157 } 158 159 int main() { 160 #ifdef DEBUG 161 freopen("in.txt","r",stdin); 162 freopen("out.txt","w",stdout); 163 #endif 164 165 init(); 166 memset(vis,0,sizeof vis); 167 Dijkstra(); 168 memset(vis,0,sizeof vis); 169 dfs_path(1); 170 memset(vis,0,sizeof vis); 171 dfs(1); 172 printf("%d %d ",ans1,ans2); 173 174 return 0; 175 }
bzoj1468

1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 7 using namespace std; 8 9 const int Maxn=40010,INF=0x3f3f3f3f; 10 11 struct Edge{ 12 int to; 13 Edge*next; 14 int w; 15 Edge(int to=0,Edge*next=0,int w=0):to(to),next(next),w(w) {} 16 }pool[Maxn*2],*fir[Maxn],*pis=pool; 17 18 void AddEdge(int from,int to,int w) { 19 *pis=Edge(to,fir[from],w);fir[from]=pis++; 20 *pis=Edge(from,fir[to],w);fir[to]=pis++; 21 } 22 23 struct Node{ 24 int s,v,r; 25 Node*ch[2]; 26 Node(int v=0):v(v){r=rand(),s=1;ch[0]=ch[1]=0;} 27 void maintain() { 28 s=1; 29 if(ch[0]) s += ch[0]->s; 30 if(ch[1]) s += ch[1]->s; 31 } 32 int cmp(int k) { 33 if(k==v) return -1; 34 return k<v?0:1; 35 } 36 }npool[Maxn],*g,*f,*nps=npool; 37 38 void rotate(Node*&o,int d) { 39 Node*t=o->ch[d]; 40 o->ch[d]=t->ch[d^1]; 41 t->ch[d^1]=o; 42 o->maintain(); 43 (o=t)->maintain(); 44 } 45 46 void insert(Node*&o,int x) { 47 if(!o) { 48 o=nps++; 49 *o=Node(x); 50 return; 51 } 52 int d=o->cmp(x); 53 if(d==-1) d=0; 54 insert(o->ch[d],x); 55 if(o->ch[d]->r < o->r) rotate(o,d); 56 o->maintain(); 57 } 58 59 void remove(Node*&o,int x) { 60 if(!o) return; 61 int d=o->cmp(x); 62 if(d==-1) { 63 if(!o->ch[0]) o=o->ch[1]; 64 else if(!o->ch[1]) o=o->ch[0]; 65 else { 66 int d2=o->ch[0]->r < o->ch[1]->r ?0:1; 67 rotate(o,d2); 68 remove(o->ch[d2^1],x); 69 } 70 }else remove(o->ch[d],x); 71 if(o) o->maintain(); 72 } 73 74 int rank(Node*o,int x) { 75 int ans=0; 76 for(int d;o;o=o->ch[d]) { 77 d=o->cmp(x); 78 if(d==-1) d=0; 79 int s=1; 80 if(o->ch[0]) s+=o->ch[0]->s; 81 if(d==1) ans += s; 82 } 83 return ans+1; 84 } 85 86 Node*kth(Node*o,int k) { 87 for(int d;o;o=o->ch[d]) { 88 int s=o->ch[0]?o->ch[0]->s:0; 89 if(k==s+1) return o; 90 if(k>s) k-= s+1,d=1; 91 else d=0; 92 } 93 return NULL; 94 } 95 96 Node*Pre(Node*o,int x) { 97 Node*ans=NULL; 98 for(int d;o;o=o->ch[d]) { 99 d=o->cmp(x); 100 if(d==-1) d=0; 101 if(d==1) ans=o; 102 } 103 return ans; 104 } 105 106 Node*Sub(Node*o,int x) { 107 Node*ans=NULL; 108 for(int d;o;o=o->ch[d]) { 109 d=o->cmp(x); 110 if(d==-1) d=1; 111 if(d==0) ans=o; 112 } 113 return ans; 114 } 115 116 template<typename Q> void maxit(Q&x,const Q&y) { 117 if(x<y) x=y; 118 } 119 int mx[Maxn],sz[Maxn]; 120 bool vis[Maxn]; 121 void dfs_size(int x,int fa) { 122 sz[x] = 1; 123 mx[x] = 0; 124 for(Edge*p=fir[x];p;p=p->next) { 125 if(vis[p->to] || p->to==fa) continue; 126 dfs_size(p->to,x); 127 sz[x] += sz[p->to]; 128 } 129 } 130 131 int root=0; 132 void dfs_root(int r,int x,int fa) { 133 maxit(mx[x],sz[r]-sz[x]); 134 if(mx[x]<mx[root]) root=x; 135 for(Edge*p=fir[x];p;p=p->next) { 136 if(vis[p->to] || p->to==fa) continue; 137 dfs_root(r,p->to,x); 138 } 139 } 140 141 int seq[Maxn],tot; 142 int K; 143 void dfs_dis(int x,int d,int fa) { 144 if(d>K) return; 145 seq[++tot]=d; 146 for(Edge*p=fir[x];p;p=p->next) if(!vis[p->to] && p->to!=fa) { 147 dfs_dis(p->to,d+p->w,x); 148 } 149 } 150 151 int ans=0; 152 153 void dfs(int x) { 154 dfs_size(x,0); 155 dfs_root(x,x,root=0); 156 vis[x=root]=1; 157 158 nps=npool; 159 f=NULL; 160 insert(f,0); 161 162 for(Edge*p=fir[x];p;p=p->next) if(!vis[p->to]) { 163 tot=0; 164 dfs_dis(p->to,p->w,x); 165 for(int i=1;i<=tot;i++) { 166 ans += rank(f,K-seq[i]+1)-1; 167 } 168 for(int i=1;i<=tot;i++) { 169 insert(f,seq[i]); 170 } 171 } 172 173 for(Edge*p=fir[x];p;p=p->next) if(!vis[p->to]) { 174 dfs(p->to); 175 } 176 } 177 178 void init() { 179 int n; 180 scanf("%d",&n); 181 for(int i=1;i<n;i++) { 182 int u,v,w; 183 scanf("%d%d%d",&u,&v,&w); 184 AddEdge(u,v,w); 185 } 186 scanf("%d",&K); 187 mx[0]=INF; 188 } 189 190 int main() { 191 #ifdef DEBUG 192 freopen("in.txt","r",stdin); 193 // freopen("out.txt","w",stdout); 194 #endif 195 196 init(); 197 dfs(1); 198 printf("%d ",ans); 199 200 return 0; 201 }
poj1741

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> using namespace std; const int Maxn=10005,INF=0x7fffffff; struct Edge{ int to,v; Edge*next; Edge(int to=0,int v=0,Edge*next=NULL):to(to),v(v),next(next){ } }pool[Maxn*2],*fir[Maxn],*pis; void AddEdge(int from,int to,int v){ *pis=Edge(to,v,fir[from]);fir[from]=pis++; *pis=Edge(from,v,fir[to]);fir[to]=pis++; } int sz[Maxn],mx[Maxn]; int vis[Maxn],clk; void dfs_size(int x,int fa) { sz[x]=1; mx[x]=0; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_size(p->to,x); sz[x] += sz[p->to]; mx[x] = max(mx[x],sz[p->to]); } } int root=0; void dfs_root(int r,int x,int fa) { mx[x] = max(mx[x],sz[r]-sz[x]); if(mx[root]>mx[x]) root=x; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_root(r,p->to,x); } } int ds[Maxn],tot; void dfs_dis(int x,int d,int fa) { ds[++tot]=d; for(Edge*p=fir[x];p;p=p->next) { if(p->to==fa || vis[p->to]==clk) continue; dfs_dis(p->to,d+p->v,x); } } int k; int calc(int x,int d) { int ret=0; tot=0; dfs_dis(x,d,0); sort(ds+1,ds+tot+1); int l=1,r=tot; for(;l<r;l++) { for(;ds[l]+ds[r]>k && l<r; r--); ret+=r-l; } return ret; } int ans; void dfs(int x) { dfs_size(x,0); root=0; dfs_root(x,x,0); vis[root]=clk; ans += calc(root,0); for(Edge*p=fir[root];p;p=p->next) { if(vis[p->to]==clk) continue; ans -= calc(p->to,p->v); dfs(p->to); } } int n; void init() { memset(mx,0,sizeof mx); mx[0]=INF; ans=0; ++clk; memset(fir,0,sizeof fir); pis=pool; int u,v,w; for(int i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&w); AddEdge(u,v,w); } } int main(){ #ifdef DEBUG freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif for(;scanf("%d%d",&n,&k)==2 && n &&k;) { init(); dfs(1); printf("%d ",ans); } return 0; }
bzoj2599

1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cmath> 7 #include<vector> 8 9 using namespace std; 10 11 const int Maxn=200005,INF=0x3f3f3f3f; 12 struct Edge{ 13 int to,v; 14 Edge*next; 15 Edge(int to=0,int v=0,Edge*next=NULL):to(to),v(v),next(next){ 16 17 } 18 }pool[Maxn*2],*fir[Maxn],*pis; 19 20 void AddEdge(int from,int to,int v){ 21 *pis=Edge(to,v,fir[from]);fir[from]=pis++; 22 *pis=Edge(from,v,fir[to]);fir[to]=pis++; 23 } 24 25 int sz[Maxn],mx[Maxn]; 26 int vis[Maxn],clk; 27 void dfs_size(int x,int fa) { 28 sz[x]=1; 29 mx[x]=0; 30 for(Edge*p=fir[x];p;p=p->next) { 31 if(p->to==fa || vis[p->to]==clk) continue; 32 dfs_size(p->to,x); 33 sz[x] += sz[p->to]; 34 mx[x] = max(mx[x],sz[p->to]); 35 } 36 } 37 38 int root=0; 39 void dfs_root(int r,int x,int fa) { 40 mx[x] = max(mx[x],sz[r]-sz[x]); 41 if(mx[root]>mx[x]) root=x; 42 43 for(Edge*p=fir[x];p;p=p->next) { 44 if(p->to==fa || vis[p->to]==clk) continue; 45 dfs_root(r,p->to,x); 46 } 47 } 48 49 int f[2000010]; 50 int g[2000010],seq[Maxn],top; 51 void dfs_dis(int x,int d,int cnt,int fa) { 52 if(d>1000000) return; 53 seq[++top]=d; 54 g[d]=min(g[d],cnt); 55 for(Edge*p=fir[x];p;p=p->next) { 56 if(p->to==fa || vis[p->to]==clk) continue; 57 dfs_dis(p->to,d+p->v,cnt+1,x); 58 } 59 } 60 61 int k; 62 int ans; 63 void dfs(int x) { 64 dfs_size(x,0); 65 root=0; 66 dfs_root(x,x,0); 67 vis[root]=clk; 68 top=0; 69 for(Edge*p=fir[root];p;p=p->next) { 70 if(vis[p->to]==clk) continue; 71 int l=top; 72 dfs_dis(p->to,p->v,1,root); 73 for(int i=l+1;i<=top;i++) if(k-seq[i]>=0) ans=min(ans,f[k-seq[i]]+g[seq[i]]); 74 for(int i=l+1;i<=top;i++) f[seq[i]]=min(f[seq[i]],g[seq[i]]),g[seq[i]]=INF; 75 g[0]=0; 76 } 77 for(int i=1;i<=top;i++) f[seq[i]]=INF; 78 f[0]=0; 79 for(Edge*p=fir[root];p;p=p->next) { 80 if(vis[p->to]!=clk) dfs(p->to); 81 } 82 } 83 int n; 84 void init() { 85 memset(mx,0,sizeof mx); 86 mx[0]=INF; 87 ans=INF; 88 ++clk; 89 memset(fir,0,sizeof fir); 90 pis=pool; 91 int u,v,w; 92 for(int i=1;i<n;i++) { 93 scanf("%d%d%d",&u,&v,&w); 94 AddEdge(u+1,v+1,w); 95 } 96 } 97 98 int main(){ 99 #ifdef DEBUG 100 freopen("in.txt","r",stdin); 101 freopen("out.txt","w",stdout); 102 #endif 103 104 memset(f,0x3f,sizeof f); 105 memset(g,0x3f,sizeof g); 106 f[0]=g[0]=0; 107 for(;scanf("%d%d",&n,&k)==2;) { 108 init(); 109 dfs(1); 110 printf("%d ",ans>=n?-1:ans); 111 } 112 113 return 0; 114 }
注意每次的辅助数组f,g清空不能用memset清空所有数字,最好统计两个max_deep来清,这样复杂度才有保证,不然就是平方级的了。
还有vis数组只是用来标记重心的,以前一直理解错了。