Tree
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 668 Accepted Submission(s): 141
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 ≤10 5),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, -10 5 ≤ k ≤ 10 5)
The first line of each case contains two integers N ,M (1 ≤ N, M ≤10 5),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, -10 5 ≤ k ≤ 10 5)
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
之前也就做了一道类似LCA的题,对LCA还不是很熟悉,比赛的时候感觉是LCA但是不会写。
看了题解,仔细想想这题其实真不难。。就是记录每个操作,最后从叶子到根网上遍历一遍,每次把要修改的值传上去就行了。。
对点u,v加w就是:add1[u]+=w,add1[v]+=w,x=lca(u,v),add[x]-=w(因为传上来两个w),因为到了x之后不能再往上传,设sub[x]+=x,每个点的add值减去sub值就是要往上传的值。
设add2[u]为u和fa[u]的边要增加的值,那么对边操作add2[u]+=w,add2[v]+=w,add2[x]-=2*w。
因为这题要按输入的顺序输出边的权值,那么还要记录u和u的父节点之间的边的编号。
注意要输入输出外挂才能过。。。。。。。
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<set>
#include<map>
#include<stack>
#define INF 0x3f3f3f3f
#define MAXN 100010
#define LOGMAXN 20
#define MAXM 1500
#define MOD 1000000007
#define MAXNODE 8*MAXN
#define eps 1e-10
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
int T,N,M,L[MAXN],anc[MAXN][LOGMAXN],fa[MAXN],e[MAXN],deg[MAXN];
LL add1[MAXN],add2[MAXN],sub[MAXN],node[MAXN],edge[MAXN];
char str[10];
struct Edge{
int to,id;
Edge(){}
Edge(int to,int id):to(to),id(id){}
};
vector<Edge> G[MAXN];
void DFS(int u,int f,int level){
L[u]=level;
int len=G[u].size();
for(int i=0;i<len;i++){
int v=G[u][i].to;
if(v!=f){
deg[u]++;
fa[v]=u;
e[v]=G[u][i].id;
DFS(v,u,level+1);
}
}
}
void lca_init(){
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){
int a=anc[i][j-1];
anc[i][j]=anc[a][j-1];
}
}
int lca(int p,int q){
if(L[p]<L[q]) swap(p,q);
int log;
for(log=0;(1<<log)<=L[p];log++);
log--;
for(int i=log;i>=0;i--) if(L[p]-(1<<i)>=L[q]) p=anc[p][i];
if(p==q) return p;
for(int i=log;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 solve(){
queue<int> q;
for(int i=1;i<=N;i++) if(!deg[i]) q.push(i); //叶子节点
while(!q.empty()){
int x=q.front();
q.pop();
node[x]=add1[x];
add1[x]-=sub[x];
edge[e[x]]=add2[x];
int f=fa[x];
add1[f]+=add1[x];
add2[f]+=add2[x];
if(!(--deg[f])) q.push(f); //子节点都处理完了,成为叶子节点
}
}
template <class T>
inline bool scan_d(T &ret) {
char c; int sgn;
if(c=getchar(),c==EOF) return 0; //EOF
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}
inline void out(long long x) {
if(x>9) out(x/10);
putchar(x%10+'0');
}
int main(){
freopen("in.txt","r",stdin);
int cas=0;
scan_d(T);
while(T--){
scan_d(N);
scan_d(M);
for(int i=1;i<=N;i++) G[i].clear();
int u,v;
for(int i=1;i<=N-1;i++){
scan_d(u);
scan_d(v);
G[u].push_back(Edge(v,i));
G[v].push_back(Edge(u,i));
}
memset(fa,0,sizeof(fa));
memset(deg,0,sizeof(deg));
DFS(1,-1,0);
lca_init();
memset(add1,0,sizeof(add1));
memset(add2,0,sizeof(add2));
memset(sub,0,sizeof(sub));
while(M--){
int u,v,w;
scanf("%s",str);
scan_d(u);
scan_d(v);
scan_d(w);
int x=lca(u,v);
if(str[3]=='1'){
add1[u]+=w;
add1[v]+=w;
add1[x]-=w;
sub[x]+=w;
}
else{
add2[u]+=w;
add2[v]+=w;
add2[x]-=w*2;
}
}
solve();
printf("Case #%d:\n",++cas);
for(int i=1;i<=N;i++){
if(i>1) printf(" ");
out(node[i]);
}
puts("");
if(N==1) puts("");
else{
for(int i=1;i<=N-1;i++){
if(i>1) printf(" ");
out(edge[i]);
}
puts("");
}
}
return 0;
}