• bzoj 2286 消耗战


    题目大意:

    一棵树 Q次询问 每次询问给K个点 求把些点都与根断开的最小代价

    思路:

    学习了一波虚树

    记录一下每个点到根的路径上边权的最小值 dp+虚树

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MAXN 500100
    12 #define Fill(a,x) memset(a,x,sizeof(a))
    13 #define to1 g1.to[i]
    14 #define to2 g2.to[i]
    15 using namespace std;
    16 inline int read()
    17 {
    18     int x=0,f=1;char ch=getchar();
    19     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    20     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    21     return x*f;
    22 }
    23 int n,f[MAXN][24],dep[MAXN],hsh[MAXN];
    24 int st[MAXN],top,tot,g[MAXN];;
    25 ll mn[MAXN];
    26 struct graph
    27 {
    28     int fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],val[MAXN<<1],cnt;
    29     graph() {Fill(fst,0);cnt=0;}
    30     void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
    31 }g1,g2;
    32 bool cmp(const int &a,const int &b) {return hsh[a]<hsh[b];}
    33 void dfs(int x,int fa)
    34 {
    35     hsh[x]=++tot;
    36     for(int i=1;(1<<i)<=dep[x];i++) f[x][i]=f[f[x][i-1]][i-1];
    37     for(int i=g1.fst[x];i;i=g1.nxt[i])
    38         if(to1!=fa) {dep[to1]=dep[x]+1,f[to1][0]=x,mn[to1]=min((ll)g1.val[i],mn[x]);dfs(to1,x);}
    39 }
    40 int lca(int u,int v)
    41 {
    42     if(dep[u]<dep[v]) swap(u,v);int t=dep[u]-dep[v];
    43     for(int i=23;~i;i--) if((1<<i)&t) u=f[u][i];
    44     if(u==v) return u;
    45     for(int i=23;~i;i--)
    46         if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
    47     return f[u][0];
    48 }
    49 void ins(int x)
    50 {
    51     if(top==1) {st[++top]=x;return ;}
    52     int y=lca(x,st[top]);
    53     if(st[top]==y) return ;
    54     while(top>1&&hsh[st[top-1]]>=hsh[y]) g2.add(st[top-1],st[top],0),top--;
    55     if(y!=st[top]) {g2.add(y,st[top],0);st[top]=y;}st[++top]=x;
    56 }
    57 ll dp(int x)
    58 {
    59     ll sum=0;
    60     for(int i=g2.fst[x];i;i=g2.nxt[i]) sum+=dp(to2);
    61     g2.fst[x]=0;
    62     return min(sum==0LL?2139062143000000000LL:sum,(ll)mn[x]);
    63 }
    64 int main()
    65 {
    66     n=read();int a,b,c;
    67     for(int i=1;i<n;i++) {a=read(),b=read(),c=read();g1.add(a,b,c);g1.add(b,a,c);}
    68     Fill(mn,127);dfs(1,0);int m=read();mn[1]=inf*100000LL;
    69     while(m--)
    70     {
    71         a=read();for(int i=1;i<=a;i++) g[i]=read();
    72         sort(g+1,g+a+1,cmp);st[top=1]=1,g2.cnt=0;
    73         for(int i=1;i<=a;i++) ins(g[i]);
    74         while(top) g2.add(st[top-1],st[top],0),top--;
    75         printf("%lld
    ",dp(1));
    76     }
    77 }
    View Code
  • 相关阅读:
    java并发系列(六)-----Java并发:volatile关键字解析(内存语义、实现原理)
    java并发系列(五)-----如何正确的关闭一个线程
    23.备忘录模式(Memento Pattern)
    22.访问者模式(Vistor Pattern)
    21.责任链模式
    20.策略者模式(Stragety Pattern)
    19.状态者模式(State Pattern)
    18.中介者模式(Mediator Pattern)
    17.观察者模式(Observer Pattern)
    16.迭代器模式(Iterator Pattern)
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9994374.html
Copyright © 2020-2023  润新知