hdu 5296 - Annoying problem(2015 Multi-University Training Contest 1 )LCA
2015-07-27 21:47
351 查看
Annoying problem
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 865 Accepted Submission(s): 286
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 ?
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<=1000000) 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=1or2,1<=y<=nx=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.
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
又是一个神题,题解是这样说的:
这也是非常神奇的,对于一个点,找他的dfs须,离他最近的两个,正好把他夹住,如果夹不住,那么找字典序最大最小的两个,然后把它加到这两个点的链上,花费就是图中的公式
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 865 Accepted Submission(s): 286
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 ?
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<=1000000) 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=1or2,1<=y<=nx=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.
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
又是一个神题,题解是这样说的:
这也是非常神奇的,对于一个点,找他的dfs须,离他最近的两个,正好把他夹住,如果夹不住,那么找字典序最大最小的两个,然后把它加到这两个点的链上,花费就是图中的公式
[code]#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #include<algorithm> using namespace std; typedef long long LL; const int maxn=100010; const int maxm=100010; const int INF=0x3f3f3f3f; int N,Q; int dep[maxn],fa[maxn],anc[maxn][20]; int num[maxn],dfn[maxn]; int head[maxn],tot,len[maxn],id[maxn]; int dfs_clock; set<int> sp; struct node { int v,next,w; }edge[maxn*2]; void init() { tot=dfs_clock=0; memset(head,-1,sizeof(head)); memset(len,0,sizeof(len)); } void dfs(int u,int f,int depth,int sum) { dep[u]=depth; dfn[u]=++dfs_clock; id[dfs_clock]=u; fa[u]=f; num[u]=1; len[u]=sum; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==f)continue; dfs(v,u,depth+1,sum+edge[i].w); num[u]+=num[v]; fa[v]=u; } } void preprocess() { for(int i=1;i<=N;i++) { anc[i][0]=fa[i]; for(int j=1;(1<<j)<=N;j++) anc[i][j]=-1; } for(int j=1;(1<<j)<=N;j++) { for(int i=1;i<=N;i++) { if(anc[i][j-1]==-1)continue; int a=anc[i][j-1]; anc[i][j]=anc[a][j-1]; } } } int LCA(int p,int q) { if(dep[p]<dep[q])swap(p,q); int k=0; while((1<<(k+1))<=dep[p])k++; for(int i=k;i>=0;i--) if(dep[p]-(1<<i)>=dep[q])p=anc[p][i]; if(p==q)return p; for(int i=k;i>=0;i--) if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i]) p=anc[p][i],q=anc[q][i]; return fa[p]; } void add_edge(int u,int v,int w) { edge[tot].v=v; edge[tot].next=head[u]; edge[tot].w=w; head[u]=tot++; } int solve(int u) { if(sp.empty())return 0; set<int>::iterator it=sp.lower_bound(u); int x=*sp.begin(); int y=*sp.rbegin(); if(y>=u&&x<=u) { x=id[*it]; it--; y=id[*it]; } else x=id[x],y=id[y]; u=id[u]; return len[u]-len[LCA(x,u)]-len[LCA(u,y)]+len[LCA(x,y)]; } int main() { int T,cas=1; int x,y,z,op; scanf("%d",&T); while(T--) { init(); scanf("%d%d",&N,&Q); for(int i=1;i<N;i++) { scanf("%d%d%d",&x,&y,&z); add_edge(x,y,z); add_edge(y,x,z); } dfs(1,-1,0,0); preprocess(); sp.clear(); int ans=0; printf("Case #%d:\n",cas++); while(Q--) { scanf("%d%d",&op,&x); x=dfn[x]; if(op==1) { if(sp.find(x)==sp.end()) { ans+=solve(x); sp.insert(x); } } else { if(sp.find(x)!=sp.end()) { sp.erase(x); ans-=solve(x); } } printf("%d\n",ans); } } return 0; }
相关文章推荐
- BNU 20860——Forwarding Emails——————【强连通图缩点+记忆化搜索】
- Equation Again 最大化最小值
- Snail—OC学习之文件操作(非读写)
- UVA 573 The Snail
- hdu-1702 ACboy needs your help again!(栈和队列的结合)
- 杭电1022 train problom
- Airbnb创始人:屌丝的逆袭之路
- epoll()无论涉及wait队列分析
- hdu杭电1702 ACboy needs your help again!【栈和队列】
- Train Problem I
- PAINT和WM_ERASEBKGND消息
- 为什么delegate属性使用assigne而不是retain?
- 220Contains Duplicate III
- Factorial Trailing Zeroes
- hdu-1022 Train Problem I (栈的简单应用)
- HDU-2057 A+B Again
- 绑定远程服务的流程aidl
- HDU 2925 Musical Chairs(约瑟夫环问题)
- Climbing Stairs
- offsetof与container_of宏(个人理解)