bzoj2286: [Sdoi2011消耗战] 虚树构造
来源:互联网 发布:数据挖掘与r语言 代码 编辑:程序博客网 时间:2024/06/07 01:14
首先我们考虑每次都做一遍树形DP(树形DP自己脑补去,随便乱搞就过了)。
显然这是TLE无疑的。
由于要改变的节点个数很少,我们可以考虑用虚树重新建图,缩小范围,这样一棵树上最多有m*2个节点
然后每次对虚树进行树形dp这样总的复杂度就是n*logn的了,logn是lca的复杂度。
然后就是各种细节的地方了。。。。。
#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>#include <vector>using namespace std;typedef long long sint;#define pii pair<int,int>#define mp make_pair#define deg 20#define maxn 501000#define inf 0x3f3f3f3f#define INF (1ll<<40)int getint(){ int res;char c; while(c=getchar(),c<'0'||c>'9'); res=c-'0'; while(c=getchar(),c>='0'&&c<='9') res=res*10+c-'0'; return res;}struct node{ int u,v,next;}tree[maxn];int first[maxn],next[maxn],to[maxn],fa[maxn][deg];sint dp[maxn];int indexs,en,en2,pre[maxn],n,dfn[maxn],dep[maxn],num,T;pii g[maxn];int vis[maxn],meet[maxn],val[maxn],minn[maxn][deg];void build(int a,int b,int c){ en++; to[en]=b; val[en]=c; next[en]=first[a]; first[a]=en;}void add(int u,int v){ en2++; tree[en2].v=v; if(vis[u]!=T) { vis[u]=T; tree[en2].next=0; } else { tree[en2].next=pre[u]; } pre[u]=en2;}void dfs(int now){ int v; indexs++; dfn[now]=indexs; for(int i=first[now];i;i=next[i]) { v=to[i]; if(v==fa[now][0]) continue; fa[v][0]=now; minn[v][0]=val[i]; for(int j=1;j<deg;j++) { fa[v][j]=fa[fa[v][j-1]][j-1]; minn[v][j]=min(minn[v][j-1],minn[fa[v][j-1]][j-1]); } dep[v]=dep[now]+1; dfs(v); }}int lca(int u,int v){ if(dep[u]<dep[v]) swap(u,v); for(int i=19;i>=0;i--) { if(dep[fa[u][i]]>=dep[v]) u=fa[u][i]; } if(u==v)return v; for(int i=19;i>=0;i--) if(fa[u][i]!=fa[v][i]) { u=fa[u][i]; v=fa[v][i]; } return fa[u][0];}int sta[maxn],top;inline long long getmin(int x,int y){ int ans=inf; if(dep[x]<dep[y]) swap(x,y); for(int i=19;i>=0;i--) if(dep[fa[x][i]]>=dep[y]) { ans=min(ans,minn[x][i]); x=fa[x][i]; } if(x==y)return ans; for(int i=19;i>=0;i--) if(fa[x][i]!=fa[y][i]) { ans=min(ans,min(minn[x][i],minn[y][i])); x=fa[x][i],y=fa[y][i]; } if(x!=y)ans=min(ans,min(minn[x][0],minn[y][0])); return ans;}void dfs2(int x){ int v; dp[x]=0; if(vis[x]==T) for(int i=pre[x];i;i=tree[i].next) { dfs2(v=tree[i].v); dp[x]+=min(getmin(v,x),meet[v]==T?inf:dp[v]); }}void virtree(){ sta[top=1]=1; for(int i=1;i<=num;i++) { int j=g[i].second; int anc=lca(sta[top],j); for(;dep[anc]<dep[sta[top]];) { if(dep[sta[top-1]]<=dep[anc]) { int last=sta[top--]; if(sta[top]!=anc)sta[++top]=anc; add(anc,last); break; } add(sta[top-1],sta[top]),top--; } if(sta[top]!=j)sta[++top]=j; } for(;top;)add(sta[top-1],sta[top]),top--;}void solve(){ int a,b,c; num=getint(); for(int i=1;i<=num;i++) { a=getint(); g[i]=mp(dfn[a],a); meet[a]=T; } sort(g+1,g+1+num); virtree(); dfs2(1); printf("%lld\n",dp[1]);}int main(){ int a,b,c; n=getint(); for(int i=1;i<n;i++) { a=getint(); b=getint(); c=getint(); build(a,b,c); build(b,a,c); } dep[1]=1; dfs(1); int cas=getint(); while(cas--) { T++;en2=0; solve(); } return 0;}/*101 5 131 9 62 1 192 4 82 3 915 6 87 5 47 8 3110 7 932 10 64 5 7 8 33 9 4 6*/
0 0
- bzoj2286: [Sdoi2011消耗战] 虚树构造
- bzoj2286: [Sdoi2011]消耗战
- bzoj2286[Sdoi2011消耗战
- [BZOJ2286] [Sdoi2011]消耗战
- [BZOJ2286][SDOI2011]消耗战
- BZOJ2286: [Sdoi2011]消耗战
- bzoj2286: [Sdoi2011消耗战
- bzoj2286【SDOI2011】消耗战
- BZOJ2286: [Sdoi2011]消耗战
- bzoj2286 [Sdoi2011]消耗战
- [BZOJ2286][Sdoi2011消耗战] 虚树
- BZOJ2286: [Sdoi2011]消耗战 虚树
- 【bzoj2286】[Sdoi2011]消耗战
- bzoj2286 [Sdoi2011]消耗战
- 【bzoj2286】【SDOI2011】消耗战
- 【bzoj2286】【sdoi2011】【消耗战】【虚树+dp】
- 【bzoj2286】[Sdoi2011消耗战 虚树+dp
- [虚树dp] bzoj2286: Sdoi2011消耗战
- 粒子波浪和颤动效果!
- 模拟慢速网络
- JS小技巧
- Ubuntu 12.04 64位安装Redmine+GIT+ReviewBoard
- Tomcat启动内存设置
- bzoj2286: [Sdoi2011消耗战] 虚树构造
- 利用NuSoap开发WebService(PHP)
- android 根据apk文件获取包名等信息 已经判断 指定 这个apk 是否安装过
- LeetCode Convert Sorted List to Binary Search Tree
- 分数拆分
- CSS的一些基础知识
- spring中强大的bean操作类BeanWrapper
- jquery Syntax error, unrecognized expression:的解决方法
- Linux文件系统损坏后的修复技巧详细介绍