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');    }}
原创粉丝点击