当前位置 : 主页 > 网页制作 > HTTP/TCP >

【SDOI2011】消耗战

来源:互联网 收集:自由互联 发布时间:2021-06-16
题面 https://www.luogu.org/problem/P2495 题解 #includecstdio #include algorithm #include vector #include stack #include iostream using namespace std;define ll long long define N 250050 ;vector int to[N],val[N]; int cnt,n; int dfu,dfin[N

题面

https://www.luogu.org/problem/P2495

题解

#include<cstdio>
#include<algorithm>
#include<vector>
#include<stack>
#include<iostream>
using namespace std;
define ll long long
define N 250050;
vector<int> to[N],val[N];
int cnt,n;
int dfu,dfin[N],dfou[N],fa[N][25],dep[N];
ll mi[N];
inline void dfs(int x) {
  dfin[x]=++dfu;
  for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
  for(int i=to[x].size()-1;i>=0;i--) {
    int y=to[x][i];
    if (dfin[y]==0) {
      dep[y]=dep[x]+1; 
      if (mi[x]<val[x][i]) mi[y]=mi[x]; else mi[y]=val[x][i];
      fa[y][0]=x;
      dfs(y);
    }
  }
  dfou[x]=++dfu;
}

inline int lca(int u,int v) {
  if (dep[u]<dep[v]) swap(u,v);
  for (int i=20;i>=0;i--) if (dep[fa[u][i]]>=dep[v]) u=fa[u][i];
  if (u==v) return u;
  for (int i=20;i>=0;i--) if (fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
  return fa[u][0];
}
int tr[4*N];
stack<int> s;
int m;
bool book[N];
ll sum[N];
inline bool cmp(int x,int y){
  int k1=(x>0)?dfin[x]:dfou[-x];
  int k2=(y>0)?dfin[y]:dfou[-y];
  return k1<k2;
}
int main(){
  scanf("%d",&n);
  for (int i=1;i<n;i++) {
    int u,v,va;
    scanf("%d %d %d",&u,&v,&va);
    to[u].push_back(v); val[u].push_back(va);
    to[v].push_back(u); val[v].push_back(va);
  }
  mi[1]=0x7f7f7f7f;
  fa[1][0]=1;
  dfs(1);
  scanf("%d",&m);
  for (int i=1;i<=m;i++) {
    int cot;
    scanf("%d",&cot);
    for (int j=1;j<=cot;j++) {
      scanf("%d",&tr[j]);
      book[tr[j]]=true; 
      sum[tr[j]]=mi[tr[j]];
    }
    sort(tr+1,tr+cot+1,cmp);
    for (int j=1;j<cot;j++) {
      int lc=lca(tr[j],tr[j+1]);
      if (!book[lc]) tr[++cot]=lc,book[lc]=true;
    }
    int nc=cot;
    for (int j=1;j<=nc;j++) tr[++cot]=-tr[j];
    if (!book[1]) tr[++cot]=1,tr[++cot]=-1;
    sort(tr+1,tr+cot+1,cmp);
    for (int j=1;j<=cot;j++) {
      if (tr[j]>0) s.push(tr[j]);
      else {
        int now=s.top(); s.pop();
        if (now!=1) {
          int fa=s.top();
          sum[fa]+=min(sum[now],mi[now]);
        }
        else printf("%lld\n",sum[1]);
        sum[now]=0; book[now]=false;
      }
    }
  }
  return 0;
}
网友评论