Topic: Given a tree, edge on the side of the right, M inquiry, each time to select some key points, the 1th node and all the key points to cut off the minimum costs required
Number of key points <=50w
First, we consider the idea of violence.
F[X] represents the minimum cost of cutting all the key points in a subtree that is rooted in X
G[X] means X is not a key point
F[x]=σmin (G[y] for each child node y of x? Inf:f[y],distance (x, y))
So every time the violence is done over the tree DP, the time complexity is O (n*m)
DFS is wasteful for all nodes now because the number of points per query does not necessarily reach the level of n
We can take out the key points of the inquiry and simulate the DFS individually
Maintain a stack, the elements of the stack form a chain from the root node, only the root node in the initial stack
Sort all key points by DFS order
Each time a node is added, the LCA of the node and the top of the stack is calculated, and all the nodes in the stack with a depth greater than the LCA are bounced off
Then put the LCA and the node into the stack, note that some duplication of circumstances to consider
In this simulated DFS process by the way the DP is done
Remember to open long long
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 250100# Define INF 0x3f3f3f3fllusing namespace std;struct abcd{int to,f,next;} Table[m<<1];int head[m],tot;int m,n,a[m];int pos[m],dpt[m],fa[m][20],dis[m][20];void Add (int x,int y,int z) { Table[++tot].to=y;table[tot].f=z;table[tot].next=head[x];head[x]=tot;} void DFS (int x) {static int cnt=0;int i;pos[x]=++cnt;dpt[x]=dpt[fa[x][0]]+1;for (i=head[x];i;i=table[i].next) if (table [I].to!=fa[x][0]) {Fa[table[i].to][0]=x;dis[table[i].to][0]=table[i].f;dfs (table[i].to);}} BOOL Compare (int x,int y) {return pos[x] < pos[y];} int LCA (int x,int y) {int j;if (dpt[x]<dpt[y]) swap (x, y), for (j=19;~j;j--) if (Dpt[fa[x][j]]>=dpt[y]) x=fa[x][j];if (x==y) return x;for (j=19;~j;j--) if (Fa[x][j]!=fa[y][j]) X=fa[x][j],y=fa[y][j];return fa[x][0];} int Distance (int x,int y) {int j,re=0x3f3f3f3f;for (j=19;~j;j--) if (Dpt[fa[x][j]]>=dpt[y]) re=min (Re,dis[x][j]), x= Fa[x][j];return re;} int main () {int i,j,k,x,y,z;cin>>n;for (i=1;i<n;i++) {scanf ("%d%d%d", &x,&y,&z); ADD (x, y, z); ADD (y,x,z);} DFS (1); for (j=1;j<=19;j++) for (i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1],dis[i][j]=min (dis[fa[i][j-1]][j-1 ],DIS[I][J-1]); static int g[m],stack[m],top;static long Long f[m];cin>>m;for (i=1;i<=m;i++) {scanf ("%d", &k); for (j=1;j<=k;j++) scanf ("%d", &a[j]); sort (a+1,a+k+1,compare); Stack[++top]=1;f[1]=0;g[1]=0;for (j=1 ; j<=k;j++) {int Lca=lca (stack[top],a[j]), while (Dpt[stack[top]]>dpt[lca]) {if (Dpt[stack[top-1]]<=dpt[lca] ) {int temp=min (G[top]? Inf:f[top], (Long Long) Distance (STACK[TOP],LCA)) stack[top--]=0;if (Lca!=stack[top]) {stack[++top]=lca;f[top]=0;g[ top]=0;} F[top]+=temp;break;} Else{f[top-1]+=min (G[top]? Inf:f[top], (Long Long) Distance (stack[top],stack[top-1]); stack[top--]=0;}} if (Stack[top]!=a[j]) {stack[++top]=a[j];f[top]=0;} G[top]=1;} while (top>1) {f[top-1]+=min (G[top]? Inf:f[top], (Long Long) Distance (stack[top],stack[top-1]); stack[top--]=0;} printf ("%lld\n", f[top--]);} return 0;} /*F[x] means that cutting off the minimum cost of all the keys in a subtree rooted in x g[x] indicates if X is the key f[x]=σmin (G[table[i].to]? Inf:f[table[i].to],distance (x,table[i].to)) */
Bzoj 2286 SDOI2011 consumption battle multiplication lca+ monotonic stack