算是入门题了,详见《分治算法在树的路径问题中的应用》(by 漆子超)。
#include #include #include #include #include #include #include #include #include #define LL long long #define INF 0x3f3f3f3f #define Mod 1000000007 #define Seed1 31 #define Seed2 37 #define EPS (1e-8) using namespace std; const int MAXE = 80010; const int MAXP = 40010; struct EDGE { int v,w,next; }edge[MAXE]; int head[MAXP]; int Top; void Link(int u,int v,int w) { edge[Top].w = w; edge[Top].v = v; edge[Top].next = head[u]; head[u] = Top++; } int PointNum[MAXP]; int MaxPointNum[MAXP]; bool STOP[MAXP];//递归时控制边界 int depth[MAXP]; int S[MAXP]; int tot; void InitGraph() { memset(STOP,false,sizeof(STOP)); memset(head,-1,sizeof(head)); Top = 0; } int getPointNum(int s,int pre) { PointNum[s] = 1; for(int i = head[s] ; i != -1; i = edge[i].next) { if(STOP[edge[i].v] || edge[i].v == pre) continue; PointNum[s] += getPointNum(edge[i].v,s); } return PointNum[s]; } void getMaxPointNum(int s,int pre,int n,int &Min,int &gc) { int Max = n-PointNum[s]; for(int i = head[s]; i != -1; i = edge[i].next) { if(STOP[edge[i].v] || edge[i].v == pre) continue; Max = max(Max,PointNum[edge[i].v]); getMaxPointNum(edge[i].v,s,n,Min,gc); } if(Min > Max) Min = Max,gc = s; } int getGC(int s,int n) { getPointNum(s,-1); int Min = n,gc = s; getMaxPointNum(s,-1,n,Min,gc); return gc; } void getDepth(int s,int pre,int len) { S[++tot] = len; depth[s] = len; for(int i = head[s];i != -1; i = edge[i].next) { if(STOP[edge[i].v] || edge[i].v == pre) continue; getDepth(edge[i].v,s,len+edge[i].w); } } int getAns(int k) { sort(S+1,S+tot+1); int ans = 0; int L = 1,R = tot; while(L < R) { if(S[L] <= k-S[R]) ans += R-L,++L; else R--; } return ans; } int dfs(int s,int n,int k) { int gc = getGC(s,n); tot = 0; getDepth(gc,-1,0); int ans = getAns(k); for(int i = head[gc];i != -1; i = edge[i].next) { if(STOP[edge[i].v]) continue; tot = 0; getDepth(edge[i].v,gc,edge[i].w); ans -= getAns(k); } STOP[gc] = true; for(int i = head[gc];i != -1; i = edge[i].next) { if(STOP[edge[i].v]) continue; ans += dfs(edge[i].v,PointNum[edge[i].v],k); } return ans; } int main() { int n,m,u,v,w,i,j,k; char dir[4]; while(scanf("%d %d",&n,&m) != EOF) { InitGraph(); for(i = 1;i <= m; ++i) { scanf("%d %d %d %s",&u,&v,&w,dir); Link(u,v,w); Link(v,u,w); } scanf("%d",&k); printf("%d\n",dfs(1,n,k)); } return 0; }