标签:
Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 7047 | Accepted: 1784 |
Description
Input
Output
Sample Input
3 3 1
1 2 1
2 3 2
0 2
1 2 3
0 3
Sample Output
1 3
题意:一个无根树,给出主角一开始所在的位置S,然后下面q个操作,操作包括查询和修改操作,对于查询操作就是当前主角的位置到目的点的距离是多少,然后主角去到那里之后就在那里等待,下次查询的时候那里就是新的起点(所以sample中第二次查询为什么是3)。修改是修改第k条边的权值,边的编号就是输入的顺序。
这题可能是数据水了还是怎么,对于修改操作虽然有优化的方法,但是用最朴素的直接遍历下去修改也是可行的,不会超时,不过时间就比较糟糕了
修改操作其实是修改了一部分子树的sum值,对于查询操作就是普通的LCA
注意:
LCA + 修改边权:一边查询两点间的距离,一边修改某些边权。对于修改了某些边的边权,就要从此开始遍历下面的子孙后代更改他们的sum值(点到根的距离)。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 5 using namespace std; 6 7 const int maxn=100000+5; 8 9 struct Edge 10 { 11 int from,to,next,w; 12 }edge[maxn<<1]; 13 14 int head[maxn]; 15 int tot; 16 17 int dep[maxn]; 18 int p[maxn][25]; 19 int sum[maxn]; 20 21 void init() 22 { 23 memset(head,-1,sizeof(head)); 24 memset(dep,0,sizeof(dep)); 25 memset(p,-1,sizeof(p)); 26 memset(sum,0,sizeof(sum)); 27 tot=1; 28 } 29 30 void addedge(int u,int v,int w) 31 { 32 edge[tot].from=u; 33 edge[tot].to=v; 34 edge[tot].w=w; 35 edge[tot].next=head[u]; 36 head[u]=tot++; 37 } 38 39 void dfs(int u,int fa) 40 { 41 for(int i=head[u];~i;i=edge[i].next) 42 { 43 int v=edge[i].to; 44 int w=edge[i].w; 45 if(!dep[v]&&v!=fa) 46 { 47 dep[v]=dep[u]+1; 48 p[v][0]=u; 49 sum[v]=sum[u]+w; 50 dfs(v,u); 51 } 52 } 53 } 54 55 void dfs2(int u,int fa) 56 { 57 for(int i=head[u];~i;i=edge[i].next) 58 { 59 int w=edge[i].w; 60 int v=edge[i].to; 61 if(v==fa) 62 continue; 63 sum[v]=sum[u]+w; 64 dfs2(v,u); 65 } 66 } 67 68 void init_lca(int n) 69 { 70 for(int j=1;(1<<j)<=n;j++) 71 { 72 for(int i=1;i<=n;i++) 73 { 74 if(p[i][j-1]!=-1) 75 p[i][j]=p[p[i][j-1]][j-1]; 76 } 77 } 78 } 79 80 void update(int u,int v,int b) 81 { 82 if(dep[u]>dep[v]) 83 swap(u,v); 84 sum[v]=sum[u]+b; 85 dfs2(v,u); 86 } 87 88 int solve(int n,int u,int v) 89 { 90 if(dep[u]<dep[v]) 91 swap(u,v); 92 93 int init_u=u; 94 int init_v=v; 95 96 int cnt; 97 for(cnt=0;(1<<cnt)<=dep[u];cnt++) 98 ; 99 cnt--; 100 101 for(int j=cnt;j>=0;j--) 102 { 103 if(dep[u]-(1<<j)>=dep[v]) 104 u=p[u][j]; 105 } 106 107 if(u==v) 108 return (sum[init_u]-sum[v]); 109 110 int lca; 111 112 for(int j=cnt;j>=0;j--) 113 { 114 if(p[u][j]!=-1&&p[u][j]!=p[v][j]) 115 { 116 u=p[u][j]; 117 v=p[v][j]; 118 } 119 } 120 121 lca=p[u][0]; 122 123 return (sum[init_u]+sum[init_v]-2*sum[lca]); 124 } 125 126 int main() 127 { 128 int n,q,s; 129 while(scanf("%d%d%d",&n,&q,&s)!=EOF) 130 { 131 init(); 132 133 for(int i=1;i<n;i++) 134 { 135 int u,v,w; 136 scanf("%d%d%d",&u,&v,&w); 137 addedge(u,v,w); 138 addedge(v,u,w); 139 } 140 141 dfs(1,-1); 142 143 init_lca(n); 144 145 /* 146 for(int i=1;i<=n;i++) 147 printf("%d\n",sum[i]); 148 */ 149 150 for(int i=0;i<q;i++) 151 { 152 int k; 153 scanf("%d",&k); 154 if(k==1) 155 { 156 int a,b; 157 scanf("%d%d",&a,&b); 158 edge[2*a-1].w=b; 159 edge[2*a].w=b; 160 update(edge[2*a].from,edge[2*a].to,b); 161 162 /* 163 for(int i=1;i<=n;i++) 164 printf("%d\n",sum[i]); 165 */ 166 167 } 168 else 169 { 170 int a; 171 scanf("%d",&a); 172 printf("%d\n",solve(n,s,a)); 173 s=a; 174 } 175 } 176 } 177 178 return 0; 179 }
POJ 2763 Housewife Wind LCA基础题
标签:
原文地址:http://www.cnblogs.com/-maybe/p/4501671.html