2286: [Sdoi2011]消耗战
来源:互联网 发布:贵州停车场车位软件 编辑:程序博客网 时间:2024/06/08 08:21
一道虚树模板题,虚树的写法我是写一个栈然后跑LCA的。
虚树建完之后一个树形DP就跑过去了。
#include<bits/stdc++.h>using namespace std;const int N = 250005 * 2;const int K = N;const int M = N * 3;#define int long longint st[N][32] , val[N][32] , cnt , stk[N] , top , node[N] , tot , lca ,depth[N] , dfn[N] , nodesize;int fir[N] , ne[M] , to[M] , C[M] , dp[N] , dfs_clock , out[N] , root;vector<int>G[N] , Val[N];void add(int x ,int y ,int z) { ne[++ cnt] = fir[x]; fir[x] = cnt; to[cnt] = y; C[cnt] = z;}void link(int x ,int y,int z) { add(x,y,z); add(y,x,z);}#define Foreachson(i,x) for(int i = fir[x];i;i = ne[i])void dfs(int x, int f , int fe) { depth[x] = depth[f] + 1; st[x][0] = f; val[x][0] = C[fe]; dfn[x] = ++ dfs_clock; for(int i = 1;i <= 30;i ++) { st[x][i] = st[st[x][i-1]][i-1]; val[x][i] = min(val[x][i - 1] , val[st[x][i-1]][i-1]); } Foreachson(i,x) { int V = to[i]; if(V != f) { dfs(V,x,i); } } out[x] = ++ dfs_clock;}int LCA_no(int x ,int y) { if(x == y) return x; if(depth[x] > depth[y]) swap(x,y); for(int i = 30;i >= 0;i --) { if(depth[st[y][i]] >= depth[x]) y= st[y][i]; } if(x == y) return x; for(int i = 30;i >= 0;i --) { if(st[y][i] != st[x][i]) { y = st[y][i]; x = st[x][i]; } } return st[x][0];}int LCA_val(int x ,int y) { if(x == y) while(1) cerr <<"Wrong Answer!"<<endl; int res = 2e9; if(depth[x] > depth[y]) swap(x,y); for(int i = 30;i >= 0;i --) { if(depth[st[y][i]] >= depth[x]) { res = min(res,val[y][i]); y = st[y][i]; } } if(x == y) return res; for(int i = 30;i >= 0;i --) { if(st[y][i] != st[x][i]) { res = min(res,val[y][i]); y = st[y][i]; res = min(res,val[x][i]); x = st[x][i]; } } return min(res , min(val[x][0],val[y][0]));}bool check(int x ,int y) { return (dfn[x] <= dfn[y] && out[x] >= out[y]);}bool cmp(int x ,int y) { return dfn[x] < dfn[y];}int vis[N];void newnode(int x ,int t) { if(vis[x] == t) return; vis[x] = t; G[x].clear(); Val[x].clear();}void newadd(int x ,int y,int z) { G[x].push_back(y); Val[x].push_back(z); G[y].push_back(x); Val[y].push_back(z);}int List[N * 2];int in[N];void dop(int x ,int f , int t) { dp[x] = 0; for(int i = 0;i <(int) G[x].size();i ++) { int V = G[x][i] , F = Val[x][i]; if(V == f) continue; dop(V,x,t); if(in[V] == t) dp[x] += F; else dp[x] += min(dp[V] , F); }}void build(int t) { int len; len = 0; scanf("%lld",&tot); List[++ len] = 1; for(int i = 2;i <= tot + 1;i ++) scanf("%lld",&List[i]) , in[List[i]] = t; len = tot + 1; //果然是要sort两遍。。。 sort(List + 1, List + len + 1, cmp); for(int i = 1;i <= tot;i ++) { List[++ len] = LCA_no(List[i] , List[i + 1]); } sort(List + 1, List + len + 1, cmp); len = unique(List + 1,List + len +1) - List - 1; for(int i = 1;i <= len ;i ++) { G[List[i]].clear(); Val[List[i]].clear(); } top = 0; for(int i = 1;i <= len;i ++) { while(top > 0 && !check(stk[top],List[i])) top --; if(!top) root = List[i]; else { newadd(stk[top] , List[i] , LCA_val(stk[top],List[i])); } stk[++ top] = List[i]; } for(int i = 1;i <= len;i ++) { dp[List[i]] = 1e18 + 666; } dop(1,0,t); printf("%lld\n",dp[1]);}int n , m;signed main() { scanf("%lld",&n); for(int i = 1 , x, y, z;i <= n- 1;i ++) { scanf("%lld%lld%lld",&x,&y,&z); link(x,y,z); } dfs(1,0,0); scanf("%lld",&m); for(int i = 1;i <= m;i ++) build(i);}
阅读全文
0 0
- 2286: [Sdoi2011消耗战
- 2286: [Sdoi2011消耗战
- BZOJ 2286: [Sdoi2011]消耗战
- bzoj 2286: [Sdoi2011]消耗战
- bzoj 2286: [Sdoi2011]消耗战
- 2286: [Sdoi2011]消耗战
- 2286: [Sdoi2011]消耗战
- BZOJ 2286: [Sdoi2011]消耗战
- bzoj 2286 [Sdoi2011]消耗战 虚树
- BZOJ 2286 [Sdoi2011]消耗战 虚树
- 【BZOJ】2286: [Sdoi2011消耗战【虚树DP】
- 【 bzoj 2286 】 : [Sdoi2011]消耗战 - 树形DP
- 2286: [Sdoi2011消耗战|树形DP|虚树
- bzoj 2286: [Sdoi2011消耗战 虚树+树形dp
- bzoj 2286 SDOI2011 消耗战 虚树dp
- 【BZOJ 2286】[Sdoi2011消耗战 虚树+dp
- bzoj 2286: [Sdoi2011]消耗战 虚树 DP
- 【BZOJ】2286 [Sdoi2011]消耗战 树形DP+虚树
- ubuntu make menuconfig出错
- Maven Build Lifecycle
- java提高篇(二)-----理解java的三大特性之继承
- Android Studio进行网络判断
- 并查集
- 2286: [Sdoi2011]消耗战
- 用简单的方法实战演练搭建http服务器(Windows上)------专为http新手
- ubuntu 配置固定ip
- 8.22上课感悟
- 广播
- 原生js中ajax访问
- 利用Android Studio、MAT对Android进行内存泄漏检测
- jquery
- 程序员的基础