BZOJ2286: [Sdoi2011]消耗战(虚树)
来源:互联网 发布:待业在家知乎 编辑:程序博客网 时间:2024/05/24 07:33
传送门
题意:
一棵树上每条边有权值,每次选k个点,并求断开一号节点到该点的最小代价。
题解:
虚树。
建树后树上dp.
#include<bits/stdc++.h>using namespace std;typedef long long ll;streambuf *ib,*ob;inline int read(){ char ch=ib->sbumpc();int i=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();} while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();} return i*f;}int buf[50];inline void W(ll x){ if(!x){ob->sputc('0');return;} if(x<0){ob->sputc('-');x=-x;} while(x)buf[++buf[0]]=x%10,x/=10; while(buf[0])ob->sputc('0'+buf[buf[0]--]);}const int Maxn=3e5+50;const ll INF=0x3f3f3f3f3f3f3f3f;typedef pair<int,int> pii;int n,m,ind,dfn[Maxn],top[Maxn],fa[Maxn],son[Maxn],sze[Maxn],dep[Maxn],id[Maxn],vt;vector<pii>edge[Maxn];vector<int>nowedge[Maxn];ll f[Maxn],mn[Maxn];inline void dp(int now,int fa2=0){ ll sum=0; if(id[now]==vt){f[now]=mn[now];return;} for(int e=nowedge[now].size()-1;e>=0;e--) { int v=nowedge[now][e]; if(v==fa2)continue; dp(v,now);sum+=f[v]; } f[now]=min(mn[now],((sum)?(sum):INF));}inline void dfs(int now,int f=0){ dfn[now]=++ind;fa[now]=f;sze[now]=1;dep[now]=dep[f]+1; for(int e=edge[now].size()-1;e>=0;e--) { int v=edge[now][e].first; if(v==f)continue; mn[v]=min(mn[now],(ll)edge[now][e].second); dfs(v,now); if(!son[now]||sze[son[now]]<sze[v])son[now]=v; sze[now]+=sze[v]; }}inline void dfs2(int now,int f=0){ if(son[now]) { top[son[now]]=top[now]; dfs2(son[now],now); } for(int e=edge[now].size()-1;e>=0;e--) { int v=edge[now][e].first; if(v==son[now]||v==f)continue; top[v]=v; dfs2(v,now); }}inline bool compid(const int &a,const int &b){ return dfn[a]<dfn[b];}inline int getlca(int x,int y){ while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); x=fa[top[x]]; } return (dep[x]>dep[y])?y:x;}inline ll solve(){ static int a[Maxn],sta[Maxn],nowtop,fa2[Maxn]; nowedge[1].clear();sta[nowtop=1]=1; int k=read();int cnt=k; for(int i=1;i<=k;i++) { a[i]=read();fa2[a[i]]=0;id[a[i]]=vt; nowedge[a[i]].clear(); } sort(a+1,a+k+1,compid); for(int i=1;i<=k;i++) { int lca=getlca(sta[nowtop],a[i]); while(dep[lca]<dep[sta[nowtop]]) { if(dep[sta[nowtop-1]]<dep[lca])fa2[sta[nowtop]]=lca; nowtop--; } if(lca!=sta[nowtop]) { a[++cnt]=lca; fa2[lca]=sta[nowtop]; sta[++nowtop]=lca; } fa2[a[i]]=sta[nowtop]; sta[++nowtop]=a[i]; } for(int i=1;i<=cnt;i++) { nowedge[fa2[a[i]]].clear(); nowedge[a[i]].clear(); } for(int i=1;i<=cnt;i++)nowedge[fa2[a[i]]].push_back(a[i]); f[1]=INF;dp(1);return f[1];}int main(){ ios::sync_with_stdio(false); cin.tie(NULL);cout.tie(NULL); ib=cin.rdbuf();ob=cout.rdbuf(); n=read();memset(mn,0x3f,sizeof(mn)); for(int i=1;i<n;i++) { int x=read(),y=read(),c=read(); edge[x].push_back(make_pair(y,c)); edge[y].push_back(make_pair(x,c)); } dfs(1);top[1]=1; dfs2(1); m=read(); while(m--) { ++vt;W(solve());ob->sputc('\n'); }}
阅读全文
0 0
- BZOJ2286: [Sdoi2011]消耗战(虚树)
- [BZOJ2286][Sdoi2011消耗战] 虚树
- BZOJ2286: [Sdoi2011]消耗战 虚树
- [BZOJ2286][SDOI2011]消耗战(虚树+树形DP)
- 【bzoj2286】【sdoi2011】【消耗战】【虚树+dp】
- 【bzoj2286】[Sdoi2011消耗战 虚树+dp
- [虚树dp] bzoj2286: Sdoi2011消耗战
- [虚树 + DP] BZOJ2286: [Sdoi2011]消耗战
- [BZOJ2286][Sdoi2011]消耗战(虚树+lca+树形dp)
- 虚树+树形dp bzoj2286【Sdoi2011】 消耗战
- BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】
- 【虚树+树形DP】BZOJ2286(Sdoi2011)[消耗战]题解
- bzoj2286: [Sdoi2011]消耗战
- bzoj2286[Sdoi2011消耗战
- [BZOJ2286] [Sdoi2011]消耗战
- [BZOJ2286][SDOI2011]消耗战
- BZOJ2286: [Sdoi2011]消耗战
- bzoj2286: [Sdoi2011消耗战
- 【预习笔记】读几个Java集合类源代码—ArrayList
- python异常处理
- 用ipython的好处
- Ubuntu 搭建VPN(PPTP)并开机自启
- C# 装箱和拆箱
- BZOJ2286: [Sdoi2011]消耗战(虚树)
- screen 命令使用
- HDU
- jQuery输入框点击添加在下面列表显示可以进行删除
- cocos2dx基础——导演类
- springboot学习笔记3(全局错误页面配置)
- Linux最常用的命令
- 使用Spring boot 创建web工程
- 月是故乡明