zoukankan      html  css  js  c++  java
  • [Sdoi2011]消耗战

    2286: [Sdoi2011]消耗战

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 3108  Solved: 1115
    [Submit][Status][Discuss]

    Description

    在 一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经 没有足够多的能源维系战斗,我军胜利在望。已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源 丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。
    侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且 会重新随机资源分布(但可以保证的是,资源不会分布到1号岛屿上)。不过侦查部门还发现了这台机器只能够使用m次,所以我们只需要把每次任务完成即可。

    Input

    第一行一个整数n,代表岛屿数量。

    接下来n-1行,每行三个整数u,v,w,代表u号岛屿和v号岛屿由一条代价为c的桥梁直接相连,保证1<=u,v<=n且1<=c<=100000。

    第n+1行,一个整数m,代表敌方机器能使用的次数。

    接下来m行,每行一个整数ki,代表第i次后,有ki个岛屿资源丰富,接下来k个整数h1,h2,…hk,表示资源丰富岛屿的编号。

    Output

    输出有m行,分别代表每次任务的最小代价。

     

    Sample Input

    10
    1 5 13
    1 9 6
    2 1 19
    2 4 8
    2 3 91
    5 6 8
    7 5 4
    7 8 31
    10 7 9
    3
    2 10 6
    4 5 7 8 3
    3 9 4 6

    Sample Output

    12
    32
    22

    HINT

     对于100%的数据,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1

      虚树DP。

    建虚树的时候,若在某个点上面有询问点,则这个点就没有用,所以这个点就不用加进虚树了。
    所以在
    DP的时候就不用开个bj数组记录哪些点是询问点,因为若一个点是询问点,那么这个点肯定是叶节点,所以就不用开数组记录了。
      1 #include<set>
      2 #include<map>
      3 #include<queue>
      4 #include<stack>
      5 #include<ctime>
      6 #include<cmath>
      7 #include<string>
      8 #include<vector>
      9 #include<cstdio>
     10 #include<cstdlib>
     11 #include<cstring>
     12 #include<iostream>
     13 #include<algorithm>
     14 #define maxn 250010
     15 #define inf 1999999999999999999ll
     16 #define LL long long
     17 using namespace std;
     18 struct data{
     19   int nex,to;
     20   LL w;
     21 }e[maxn*2],g[maxn*2];
     22 int head[maxn],edge=0,head1[maxn],edge1=0;
     23 int dfn[maxn],a[maxn],deep[maxn],size[maxn];
     24 int f[maxn][20],Stack[maxn];
     25 LL dis[maxn],dp[maxn];
     26 bool bj[maxn];
     27 inline void add(int from,int to,int w){
     28   if(from==to) return;
     29   e[++edge].nex=head[from];
     30   e[edge].to=to;
     31   e[edge].w=w;
     32   head[from]=edge;
     33 }
     34 inline void link(int from,int to){
     35   if(from==to) return;
     36   g[++edge1].nex=head1[from];
     37   g[edge1].to=to;
     38   head1[from]=edge1;
     39 }
     40 int de=0;
     41 void dfs(int x,int fa){
     42   ++de;
     43   dfn[x]=de;
     44   size[x]++;
     45   for(int i=head[x];i;i=e[i].nex){
     46     int u=e[i].to;
     47     if(u==fa) continue;
     48     f[u][0]=x;
     49     deep[u]=deep[x]+1;
     50     dis[u]=min(dis[x],e[i].w);
     51     dfs(u,x);
     52     size[x]+=size[u];
     53   }
     54 }
     55 void DP(int x,int fa){
     56   LL ans=0;
     57   dp[x]=dis[x];
     58   for(int i=head1[x];i;i=g[i].nex){
     59     int u=g[i].to;
     60     if(u==fa) continue;
     61     DP(u,x);
     62     ans+=dp[u];
     63   }
     64   head1[x]=0;
     65   if(!ans) dp[x]=dis[x];
     66   else if(ans<dp[x]) dp[x]=ans;
     67 }
     68 inline int lca(int x,int y){
     69   if(deep[x]<deep[y]) swap(x,y);
     70   for(int i=18;i>=0;i--)
     71     if(deep[f[x][i]]>=deep[y]) x=f[x][i];
     72   if(x==y) return x;
     73   for(int i=18;i>=0;i--)
     74     if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
     75   return f[x][0];
     76 }
     77 bool cmp(int a,int b){
     78   return dfn[a]<dfn[b];
     79 }
     80 inline void build(){
     81   int tot=0,m,top=0,LCA;scanf("%d",&m);
     82   for(int i=1;i<=m;i++) scanf("%d",&a[i]);
     83   sort(a+1,a+m+1,cmp);
     84   a[++tot]=a[1]; 
     85   for(int i=2;i<=m;i++) if(lca(a[i],a[tot])!=a[tot]) a[++tot]=a[i];
     86   Stack[++top]=1;
     87   for(int i=1;i<=tot;i++){
     88     if(top==0){Stack[++top]=a[i];continue;}
     89     LCA=lca(Stack[top],a[i]);
     90     while(1){
     91       if(deep[Stack[top-1]]<=deep[LCA]){
     92     link(Stack[top],LCA),link(LCA,Stack[top]);
     93     top--;
     94     if(Stack[top]!=LCA) Stack[++top]=LCA;
     95     break;
     96       }
     97       link(Stack[top],Stack[top-1]),link(Stack[top-1],Stack[top]);
     98       top--;
     99     }
    100     if(Stack[top]!=a[i])
    101       Stack[++top]=a[i];
    102   }
    103   while(top>1)link(Stack[top],Stack[top-1]),link(Stack[top-1],Stack[top]),top--;
    104   top--;
    105   DP(1,0);
    106   printf("%lld
    ",dp[1]);
    107   edge1=0;
    108 }
    109 int main()
    110 {
    111   freopen("!.in","r",stdin);
    112   freopen("!.out","w",stdout);
    113   int n,x,y,z,qes;
    114   scanf("%d",&n);
    115   for(int i=1;i<n;i++)
    116     scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
    117   deep[1]=1,dis[1]=inf;
    118   dfs(1,0);
    119   for(int i=1;i<=18;i++)
    120     for(int j=1;j<=n;j++)
    121       f[j][i]=f[f[j][i-1]][i-1];
    122   scanf("%d",&qes);
    123   for(int i=1;i<=qes;i++)
    124     build();
    125   return 0;
    126 }
    
    
    
     
  • 相关阅读:
    无向图的双连通分量
    word发布博客
    构造泛型类型变量数组
    利用函数式接口和反射实例化泛型类型变量
    java8 lambda方法引用
    java8 常用函数式接口
    第一章 java程序设计概述
    算法基础~链表~从位置m到n逆序
    算法基础~链表【将链表逆序题(不可申请额外的空间)~头插法】
    Css定位的bug(margin导致的bug)
  • 原文地址:https://www.cnblogs.com/pantakill/p/6679658.html
Copyright © 2011-2022 走看看