hdu5044 Tree
Tree
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 845 Accepted Submission(s): 162
Problem Description
You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N
There are N - 1 edges numbered from 1 to N - 1.
Each node has a value and each edge has a value. The initial value is 0.
There are two kind of operation as follows:
● ADD1 u v k: for nodes on the path from u to v, the value of these nodes increase by k.
● ADD2 u v k: for edges on the path from u to v, the value of these edges increase by k.
After finished M operation on the tree, please output the value of each node and edge.
There are N - 1 edges numbered from 1 to N - 1.
Each node has a value and each edge has a value. The initial value is 0.
There are two kind of operation as follows:
● ADD1 u v k: for nodes on the path from u to v, the value of these nodes increase by k.
● ADD2 u v k: for edges on the path from u to v, the value of these edges increase by k.
After finished M operation on the tree, please output the value of each node and edge.
Input
The first line of the input is T (1 ≤ T ≤ 20), which stands for the number of test cases you need to solve.
The first line of each case contains two integers N ,M (1 ≤ N, M ≤105),denoting the number of nodes and operations, respectively.
The next N - 1 lines, each lines contains two integers u, v(1 ≤ u, v ≤ N ), denote there is an edge between u,v and its initial value is 0.
For the next M line, contain instructions “ADD1 u v k” or “ADD2 u v k”. (1 ≤ u, v ≤ N, -105 ≤ k ≤ 105)
The first line of each case contains two integers N ,M (1 ≤ N, M ≤105),denoting the number of nodes and operations, respectively.
The next N - 1 lines, each lines contains two integers u, v(1 ≤ u, v ≤ N ), denote there is an edge between u,v and its initial value is 0.
For the next M line, contain instructions “ADD1 u v k” or “ADD2 u v k”. (1 ≤ u, v ≤ N, -105 ≤ k ≤ 105)
Output
For each test case, print a line “Case #t:”(without quotes, t means the index of the test case) at the beginning.
The second line contains N integer which means the value of each node.
The third line contains N - 1 integer which means the value of each edge according to the input order.
The second line contains N integer which means the value of each node.
The third line contains N - 1 integer which means the value of each edge according to the input order.
Sample Input
2
4 2
1 2
2 3
2 4
ADD1 1 4 1
ADD2 3 4 2
4 2
1 2
2 3
1 4
ADD1 1 4 5
ADD2 3 2 4
Sample Output
Case #1:
1 1 0 1
0 2 2
Case #2:
5 0 0 5
0 4 0
Source
思路:先求lca,对于点的修改,对于 u,v,假设 lca等于 u ,那么add[v] += val ;add[fa[u]] -= val ;
如果lca不为 u,v那么 ......看代码吧,
最后从根节点开始 up , add[fa] += add[son] ; 这个add[u],就是u 增加的值
对于边的修改,我们先转为有根树,然后把边的权值分给两个端点中,深度高的那个,然后
就可以和点修改差不多了,具体看代码吧
这题真吭,很和谐的树链分割过不了。。。。
#pragma comment(linker,"/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<vector> #include<set> #include<stack> #include<map> #include<ctime> #include<bitset> #define LL long long #define INF 999999 #define mod 20140518 #define maxn 100010 using namespace std; int head[maxn],next1[maxn*2],to[maxn*2] ; int top ,id[maxn] ,n ,num[maxn],dep[maxn]; int xx[maxn],yy[maxn],cc[maxn],e[maxn]; int fa[maxn]; LL ans[maxn],add1[maxn],add2[maxn]; int out[maxn]; bool vi[maxn] ; struct node { int v,id; node(){} node(int x,int y ) { v = x ;id = y ; } }; vector<node>qe[maxn]; void Unit(int u,int v ) { next1[top] = head[u] ;to[top] = v ; head[u] = top++; } int find(int x ) { if(x != fa[x]) fa[x] = find(fa[x]) ; return fa[x]; } void dfs(int u ,int f) { fa[u]=u; vi[u] = true; for(int i = head[u] ; i != -1 ; i = next1[i]) { int v = to[i] ; if(v==f) continue; dfs(v,u) ; fa[v] = u ; } node a; for(int i = 0 ; i < qe[u].size();i++) { a = qe[u][i] ; if(!vi[a.v]) continue ; num[a.id] = find(a.v) ; } } void bfs(int s) { memset(vi,0,sizeof(vi)) ; memset(out,0,sizeof(out)); queue<int>q ; q.push(s) ; dep[s]=0; vi[s] = true ; while(!q.empty()) { int u = q.front() ; q.pop() ; for(int i = head[u] ; i != -1 ; i = next1[i]) { int v = to[i] ; if(vi[v]) continue ; out[u]++; vi[v] = true ; dep[v]=u; id[v] = i/2+1 ; q.push(v) ; } } } int next_int() { char ch; int res; bool neg; while (ch = getchar(), !isdigit(ch) && ch != '-') ; if (ch == '-') { neg = true; res = 0; } else { neg = false; res = ch - '0'; } while (ch = getchar(), isdigit(ch)) res = res * 10 + ch - '0'; return neg ? -res : res; } int main() { char a[10] ; int m,x,y,i,j,u,v; int T,c ,case1=0; cin >> T ; while( T-- ) { scanf("%d%d",&n,&m) ; for(i = 0 ; i <= n ;i++)qe[i].clear(); memset(head,-1,sizeof(head)) ; top=0; for( i = 1 ; i < n ;i++) { x = next_int(); y = next_int(); Unit(x,y) ; Unit(y,x) ; } bfs(1) ; for( i = 1 ; i <= m ;i++) { scanf("%s",a) ; x = next_int(); y = next_int(); c = next_int(); qe[x].push_back(node(y,i)); qe[y].push_back(node(x,i)); xx[i]=x;yy[i]=y; cc[i]=c; if(a[3]=='1') { e[i]=1; } else { e[i]=0; } } memset(vi,0,sizeof(vi)) ; memset(add1,0,sizeof(add1)); memset(add2,0,sizeof(add2)); dfs(1,-1); int f; for( i = 1 ; i <= m ;i++) { f = num[i]; u=xx[i]; v=yy[i]; if(e[i]) { if(u==v) { add1[u] += cc[i]; add1[dep[f]] -= cc[i]; } else{ add1[u] += cc[i]; add1[v] += cc[i]; add1[dep[f]] -= cc[i]; add1[f] -= cc[i]; } } else{ if(u==v) { add2[u] += cc[i]; add2[f] -= cc[i]; } else{ add2[u] += cc[i]; add2[v] += cc[i]; add2[f] -= 2*cc[i]; } } } queue<int>q; for( i = 1 ; i <= n ;i++)if(!out[i]) { q.push(i); } memset(vi,0,sizeof(vi)); while(!q.empty()) { u = q.front();q.pop(); v = dep[u] ; if(v==0) continue ; add1[v] += add1[u] ; add2[v] += add2[u] ; out[v]--; if(out[v]==0)q.push(v); } printf("Case #%d:\n",++case1); bool flag=false; for( i = 1 ; i <= n ;i++) { if(flag)printf(" ") ; flag=true; printf("%I64d",add1[i]); } puts(""); flag=false; for( i = 2 ; i <= n ;i++) { ans[id[i]] = add2[i]; } for( i = 1 ; i <n ;i++) { if(flag) printf(" ") ; flag=true; printf("%I64d",ans[i]); } puts(""); } return 0 ; }