Annoying problem
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1006 Accepted Submission(s): 330
Problem Description
Coco has a tree, whose nodes are conveniently labeled by 1,2,…,n, which has n-1 edge,each edge has a weight. An existing set S is initially empty.
Now there are two kinds of operation:
1 x: If the node x is not in the set S, add node x to the set S
2 x: If the node x is in the set S,delete node x from the set S
Now there is a annoying problem: In order to select a set of edges from tree after each operation which makes any two nodes in set S connected. What is the minimum of the sum of the selected edges’ weight ?
Now there are two kinds of operation:
1 x: If the node x is not in the set S, add node x to the set S
2 x: If the node x is in the set S,delete node x from the set S
Now there is a annoying problem: In order to select a set of edges from tree after each operation which makes any two nodes in set S connected. What is the minimum of the sum of the selected edges’ weight ?
Input
one integer number T is described in the first line represents the group number of testcases.( T<=10 )
For each test:
The first line has 2 integer number n,q(0<n,q<=100000) describe the number of nodes and the number of operations.
The following n-1 lines each line has 3 integer number u,v,w describe that between node u and node v has an edge weight w.(1<=u,v<=n,1<=w<=100)
The following q lines each line has 2 integer number x,y describe one operation.(x=1 or 2,1<=y<=n)
For each test:
The first line has 2 integer number n,q(0<n,q<=100000) describe the number of nodes and the number of operations.
The following n-1 lines each line has 3 integer number u,v,w describe that between node u and node v has an edge weight w.(1<=u,v<=n,1<=w<=100)
The following q lines each line has 2 integer number x,y describe one operation.(x=1 or 2,1<=y<=n)
Output
Each testcase outputs a line of "Case #x:" , x starts from 1.
The next q line represents the answer to each operation.
The next q line represents the answer to each operation.
Sample Input
1
6 5
1 2 2
1 5 2
5 6 2
2 4 2
2 3 2
1 5
1 3
1 4
1 2
2 5
Sample Output
Case #1:
0
6
8
8
4
Author
FZUACM
Source
解题:LCA居然可以解决这种问题。。。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 100010; 4 struct arc { 5 int to,w,next; 6 arc(int x = 0,int y = 0,int z = -1) { 7 to = x; 8 w = y; 9 next = z; 10 } 11 } e[maxn*20]; 12 int head[maxn],fa[maxn][20],dep[maxn],ti,tot; 13 int n,q,timeStamp[maxn],node[maxn],dfn[maxn]; 14 void add(int u,int v,int w) { 15 e[tot] = arc(v,w,head[u]); 16 head[u] = tot++; 17 } 18 void dfs(int u,int f) { 19 timeStamp[u] = ++ti; 20 node[ti] = u; 21 for(int i = head[u]; ~i; i = e[i].next) { 22 if(e[i].to == f) continue; 23 dfn[e[i].to] = dfn[u] + e[i].w; 24 fa[e[i].to][0] = u; 25 dep[e[i].to] = dep[u] + 1; 26 for(int j = 1; j < 19; ++j) 27 fa[e[i].to][j] = fa[fa[e[i].to][j-1]][j-1]; 28 dfs(e[i].to,u); 29 } 30 } 31 int LCA(int u,int v) { 32 if(dep[u] < dep[v]) swap(u,v); 33 int log; 34 for(log = 1; (1<<log) <= dep[u]; ++log); 35 for(int i = log-1; i >= 0; --i) 36 if(dep[u] - (1<<i) >= dep[v]) u = fa[u][i]; 37 if(u == v) return u; 38 for(int i = log-1; i >= 0; --i) { 39 if(fa[u][i] != fa[v][i]) { 40 u = fa[u][i]; 41 v = fa[v][i]; 42 } 43 } 44 return fa[u][0]; 45 } 46 set<int>st; 47 int solve(int u) { 48 if(st.empty()) return 0; 49 int x,y; 50 auto it = st.upper_bound(u); 51 if(it == st.begin() || it == st.end()) { 52 x = node[*st.begin()]; 53 y = node[*st.rbegin()]; 54 } else { 55 x = node[*it]; 56 y = node[*(--it)]; 57 } 58 u = node[u]; 59 return dfn[u] - dfn[LCA(x,u)] - dfn[LCA(y,u)] + dfn[LCA(x,y)]; 60 } 61 bool used[maxn]; 62 int main() { 63 int kase,u,v,w,op,cs = 1; 64 scanf("%d",&kase); 65 while(kase--) { 66 memset(head,-1,sizeof head); 67 memset(used,false,sizeof used); 68 scanf("%d%d",&n,&q); 69 for(int i = ti = tot = 0; i < n-1; ++i) { 70 scanf("%d%d%d",&u,&v,&w); 71 add(u,v,w); 72 add(v,u,w); 73 } 74 dep[1] = 1; 75 int ret = dfn[1] = 0; 76 dfs(1,-1); 77 st.clear(); 78 printf("Case #%d: ",cs++); 79 while(q--) { 80 scanf("%d%d",&op,&u); 81 u = timeStamp[u]; 82 if(op == 1 && !used[u]) { 83 used[u] = true; 84 ret += solve(u); 85 st.insert(u); 86 } else if(op == 2 && used[u]) { 87 used[u] = false; 88 st.erase(u); 89 ret -= solve(u); 90 } 91 printf("%d ",ret); 92 } 93 } 94 return 0; 95 }