bzoj2286 sdoi2011 消耗战

我要去死,,,,
虚树模板提,,真是够了我自己写的模板没错,,,第一次我是用的多次memset,所以T了,,,第二次,,学会了不用memset直接dp时清零结果有些节点没有覆盖所以有T了,,tm的分数还一样于是我就以为我的模板有问题就可劲差错可劲查错,是我dp写残了,,,我去死吧!!!
知识点:1.虚树 2.不要每次都用memset那一定会T,,而且注意细节,学会每次完成时顺便清零 3.错误有可能就在你想不到的地方,,,

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#define N 250000
using namespace std;
typedef long long LL;
struct edge{ int point,nxt,v,w;};
edge e1[(N<<2)+5],e2[(N<<2)+5];
LL f[N+5];
int x,a[N+5],fa[N+5][22],deep[N+5],cnt1,cnt2,top,st[N+5],dfn[N+5],n,mini[N+5];
bool used[N+5],exist[N+5];
void addedge1(int u1,int v1,int w1){
    e1[++cnt1].nxt = e1[u1].point; e1[u1].point = cnt1; e1[cnt1].v = v1; e1[cnt1].w =w1; }
void insert1(int u1,int v1,int w1){ addedge1(u1,v1,w1); addedge1(v1,u1,w1);}
void addedge2(int u1,int v1,int w1){
    e2[++cnt2].nxt = e2[u1].point; e2[u1].point = cnt2; e2[cnt2].v = v1; e2[cnt2].w =w1; }
void insert2(int u1,int v1,int w1){ addedge2(u1,v1,w1); addedge2(v1,u1,w1);}
bool cmp(int a,int b){ return dfn[a]<dfn[b];}
int getnum(){
    char c; int num;
    while (!isdigit(c=getchar()));
    num = c - '0';
    while (isdigit( c= getchar())) num = 10*num + c -'0';
    return num;
}

void dfs(int x){
    dfn[x] = ++top;
    for (int i = 1; i <= 20; ++i) 
      fa[x][i] = fa[fa[x][i-1]][i-1];
     // c[x][i] = c[x][i-1];
     // if (fa[x][i-1]!=0) c[x][i] = min(c[x][i],c[fa[x][i-1]][i-1]);}
    for (int p = e1[x].point; p; p = e1[p].nxt)
      if (!dfn[e1[p].v]){
         deep[e1[p].v] = deep[x]+1; fa[e1[p].v][0] = x; mini[e1[p].v] = min(mini[x],e1[p].w);
         dfs(e1[p].v);
      }
}

void init(){
    cnt1 = 0; top = 0; mini[1] = 0x7fffffff;
    n = getnum();
    memset(e1,0,sizeof(e1));
    for (int i = 1; i < n; ++i) {
    int u1=getnum(),v1=getnum(),w1=getnum();
    insert1(u1,v1,w1);}
    //cout<<e1[1].point<<endl<<e1[6].nxt<<endl; 
    //for (int p = e1[1].point;p;p=e1[p].nxt) cout<<e1[p].v<<endl;
    dfs(1);
    //for (int i = 1; i<=n;++i) cout<<dfn[i]<<endl;
}

int LCA(int u,int v){
    if (deep[u] < deep[v]) swap(u,v);
    int  l = deep[u] - deep[v];
    for (int i = 0; i <= 20; ++i)
      if (l&(1<<i)) u = fa[u][i];
    for (int i = 20 ; i  >=0; --i)
      if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
    if (u!=v) return fa[u][0];
    return u;
}

void make_it(){
    x = getnum();  top = 0;
    cnt2 = 0;
    for (int i = 1; i <=x;++i) a[i] = getnum();
    st[0] = 1;
    sort(a+1,a+x+1,cmp);
    for (int i = 1; i <=x; ++i) exist[a[i]] = 1;
    for (int i = 1; i <= x; ++i){
        int lca = LCA(a[i],st[top]);
        while ((top)&&(deep[lca] < deep[st[top]])){
            if (deep[st[top-1]]<=deep[lca]) 
             {insert2(st[top],lca,mini[st[top]]); --top; break;}
            insert2(st[top-1],st[top],mini[st[top]]);
            top--;
        }
        if (st[top] != lca)  st[++top] = lca;
        if (st[top] != a[i]) st[++top] = a[i];
    }
    while (top) { insert2(st[top-1],st[top],mini[st[top]]); top--;}
}

void dp(int x){
    f[x] = 0;
    for (int p = e2[x].point; p ;p = e2[p].nxt)
      if (deep[e2[p].v]>deep[x]) {
         dp(e2[p].v);
        if (exist[e2[p].v]) f[x] += e2[p].w;
        else f[x] += min((LL)e2[p].w,f[e2[p].v]);}
    e2[x].point = 0;
}

void DO_IT(){
    int m;
    m = getnum();
    while (m--){
        make_it();
        dp(1);
        for (int i = 1; i<=x;++i) exist[a[i]] = 0;
        printf("%lld\n",f[1]);
    }

}

int main(){
    init();
    DO_IT();
    return 0;
}

你可能感兴趣的:(bzoj2286 sdoi2011 消耗战)