• HDU 5296 Annoying problem dfs序 lca set


    Annoying problem

    Problem Description
    Coco has a tree, whose nodes are conveniently labeled by 1,2,…,n, which has n-1 edge,each edge has a weight. An existing set S is initially empty.
    Now there are two kinds of operation:

    1 x: If the node x is not in the set S, add node x to the set S
    2 x: If the node x is in the set S,delete node x from the set S

    Now there is a annoying problem: In order to select a set of edges from tree after each operation which makes any two nodes in set S connected. What is the minimum of the sum of the selected edges’ weight ?

     
    Input
    one integer number T is described in the first line represents the group number of testcases.( T<=10 ) 
    For each test:
    The first line has 2 integer number n,q(0<n,q<=100000) describe the number of nodes and the number of operations.
    The following n-1 lines each line has 3 integer number u,v,w describe that between node u and node v has an edge weight w.(1<=u,v<=n,1<=w<=100)
    The following q lines each line has 2 integer number x,y describe one operation.(x=1 or 2,1<=y<=n)


     
    Output
    Each testcase outputs a line of "Case #x:" , x starts from 1.
    The next q line represents the answer to each operation.

     
    Sample Input
    1 6 5 1 2 2 1 5 2 5 6 2 2 4 2 2 3 2 1 5 1 3 1 4 1 2 2 5
     
    Sample Output
    Case #1: 0 6 8 8 4
     
    Author
    FZUACM
     

    题意:

    给出一棵树,每个边都有一个权值,现在有一个空的集合,两种操作,

    1 x吧x节点放到集合中(如果还没放入)

    2 x把x节点从集合中拿出来(已放入)。

    每次操作后输出最小的边权和,保证这些边可以将这些点连起来。

    题解:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include<vector>
    #include<set>
    using namespace std;
    const int N = 1e5+20, M = 30005, mod = 1000000007, inf = 0x3f3f3f3f;
    typedef long long ll;
    //不同为1,相同为0
    int in[N],dis[N],head[N],t,vis[N],fa[N][18],deep[N],cas=1,ff[N],cur,v[N];
    vector<pair<int ,int > >G[N];
    set<int >s;
    struct edge{int to,next,v;}e[N*4];
    void add(int u,int v,int val) {e[t].to = v;e[t].next = head[u];e[t].v = val; head[u]=t++;}
    void dfs(int x,int f) {
        in[x] = cur;
        ff[cur] = x;
        cur++;
        for(int i=0;i<G[x].size();i++) {
            if(G[x][i].first!=f) {
                dis[G[x][i].first] = dis[x]+G[x][i].second;
                dfs(G[x][i].first,x);
            }
        }
    }
    void dfs1(int x) {
        vis[x] =1;
        for(int i=1;i<=17;i++) {
            if(deep[x] < (1<<i)) break;
            fa[x][i] = fa[fa[x][i-1]][i-1];
        }
        for(int i=head[x];i;i=e[i].next) {
            if(vis[e[i].to]) continue;
            deep[e[i].to] = deep[x]+1;
            fa[e[i].to][0] = x;
            dfs1(e[i].to);
        }
    }
    int lca(int x,int y) {
        if(deep[x] < deep[y]) swap(x,y);
        int t = deep[x] - deep[y];
        for(int i=0;i<=17;i++)
            if(t&(1<<i)) x = fa[x][i];
        for(int i=17;i>=0;i--)
        if(fa[x][i]!=fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
        if(x==y) return x;
        return fa[x][0];
    }
    int solve(int u){
    if (s.empty())
      return 0;
     int x, y;
       set<int>::iterator it = s.lower_bound(u), itx = it;
     itx--;
     if (it == s.end() || it == s.begin()) {
      it = s.begin();
      itx = s.end();
      itx--;
     }
     y = (*it);
     x = (*itx);
      y = ff[y];
     x =ff[x];
     u=ff[u];
     //cout<<u<<" "<<x<<" "<<y<<endl;
        return dis[u]-dis[lca(u,x)]-dis[lca(u,y)]+dis[lca(x,y)];
    }
    void init() {
        int n,m;
        for(int i=0;i<N;i++) G[i].clear();s.clear();
        memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        memset(dis,0,sizeof(dis));
         memset(v,0,sizeof(v));
        memset(deep,0,sizeof(deep));
        memset(ff,0,sizeof(ff));
         memset(fa,0,sizeof(fa));
         memset(in,0,sizeof(in));
        cur=1;t=1;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n-1;i++) {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            G[a].push_back(make_pair(b,c));
            G[b].push_back(make_pair(a,c));
            add(a,b,c);
            add(b,a,c);
        }
        dfs(1,1);dfs1(1);int ans=0;
        printf("Case #%d:
    ",cas++);
        for(int i=1;i<=m;i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            b=in[b];
            if(a==1) {
                 if(!v[b]){
                                 v[b]=1;
                            if(s.size()==0){
                                s.insert(b);
                            }
                            else{
                                ans+=solve(b);
                                s.insert(b);
                            }
                        }
            }
            else {
                  if(v[b]){
                                    v[b]=0;
                                    s.erase(b);
                                    if(s.size()!=0){
                                        ans-=solve(b);
                                    }
                        }
            }
            printf("%d
    ",ans);
        }
    }
    int main() {int T;
        scanf("%d",&T);
        while(T--) {
            init();
        }
        return 0;
    }
  • 相关阅读:
    Silerlight 控制datagrid控件多选时不显示详细信息
    正则表达式限制文本框只能输入数字,小数点,英文字母,汉字
    图片正则表达式
    css最小高度,最大高度important
    让网页变灰色兼容各种浏览器
    edecms v5.7模块管理列表为空没有内容
    统一日志的记录格式,用宏调用printf
    出差
    使窗体在指定窗口的顶层
    C BNF grammar
  • 原文地址:https://www.cnblogs.com/zxhl/p/5273290.html
Copyright © 2020-2023  润新知