zoukankan      html  css  js  c++  java
  • HDU 5296 Annoying problem


    Annoying problem

    Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 203    Accepted Submission(s): 60


    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
     

    Source
     


    #include <bits/stdc++.h>
    using namespace std;
    #define prt(k) cerr<<#k" = "<<k<<endl
    typedef unsigned long long ll;
    
    const int N = 233333;
    int n, m, head[N], mm;
    struct Edge
    {
        int to, next, w;
    } e[N << 1];
    void add(int u, int v, int w = 1)
    {
        e[mm].to = v;
        e[mm].next = head[u];
        e[mm].w = w;
        head[u] = mm++;
    }
    int sz[N], dep[N];
    int f[N][22]; /// f[i][j] 表示 i 的第 2^j 个祖先
    int dfn[N];  ///dfs index
    int cur;
    int id[N]; /// you dfs xu qiu chu bian hao
    int len[N];
    void dfs(int u, int fa) /// 点从 1 開始标号
    {
        f[u][0] = fa;
        sz[u] = 1;
        dfn[u] = ++cur;
        id[cur] = u;
        for (int i=head[u]; ~i; i=e[i].next)
        {
            int v = e[i].to;
            int w = e[i].w;
            if (v != fa)
            {
                dep[v] = dep[u] + 1;
                len[v] = len[u] + w;
                dfs(v, u);
                sz[u] += sz[v];
            }
        }
    }
    int maxh;
    void gao()
    {
        cur = 0;
        dep[0] = -1;
        len[1] = dep[1] = 0;
        f[1][0] = 1;
        dfs(1, 0);f[1][0] = 1;
        int j;
        for (j=1; (1<<j)<n; j++)
            for (int i=1; i<=n; i++)
                f[i][j] = f[f[i][j-1]][j-1];
        maxh = j - 1;
    }
    int swim(int x, int k)
    {
        for (int i=0; i<=maxh; i++)
            if (k >> i & 1)
                x = f[x][i];
        return x;
    }
    int LCA(int x, int y)
    {
        if (dep[x] > dep[y]) swap(x, y); ///dep[x] <= dep[y];
        y = swim(y, dep[y] - dep[x]);
        if (x == y) return y;
        for (int i=maxh; i>=0; i--)
        {
            if (f[x][i] != f[y][i])
                x = f[x][i], y = f[y][i];
        }
        return f[x][0];
    }
    int Q;
    
    set<int> se;
    set<int>::iterator it;
    int dist(int x, int y)
    {
        int lca = LCA(x, y);
        return len[x] - len[lca] + len[y] - len[lca];
    }
    int solve(int u)
    {
        if (se.empty()) return 0;
        int x, y;
        int t = *se.begin();
        it = se.lower_bound( u);
        y = *it;
        it--;
        x = *(it );
        int t2 = *se.rbegin();
        x = id[x];
        y = id[y];
        if (t2 < u || t > u)
        {
            x = id[t]; y = id[t2];
        }
        u = id[u];
        return len[u] - len[LCA(x,u) ] - len[LCA(y,u)] + len[LCA(x,y) ];
    }
    int main()
    {
        int re;
        cin>>re;
        int ca=1;
        while (re--)
        {
            cin>>n>>Q;
            mm = 0;
            memset(head,-1,sizeof head);
            for (int i=0; i<n-1; i++)
            {
                int u, v, w;
                scanf("%d%d%d", &u, &v, &w);
                add(u, v, w);
                add(v, u, w);
            }
            gao();
            printf("Case #%d:
    ", ca++);
            se.clear();
            int ans = 0;
            while (Q--)
            {
                int op, u;
                scanf("%d%d", &op, &u);
                u = dfn[u];
                if (op==1)
                {
                    it = se.find(u);
                    if (it==se.end())
                    {
                        ans += solve(u);
                        se.insert(u);
                    }
                }
                else
                {
                    it = se.find(u);
                    if (it != se.end())
                    {
                        se.erase(u);
                        ans -= solve(u);
                    }
                }
                printf("%d
    ", ans);
            }
        }
        return 0;
    }
    


  • 相关阅读:
    实现Bootstrap表格拖拽
    鼠标悬停显示气泡
    JS实现当前选择日期是星期几
    JS实现双击编辑可修改
    数组累计-reduce
    vuex——action,mutation,getters的调用
    正则 二
    常用正则 一
    vuex 的使用 mapState, mapGetters, mapMutations, mapActions
    正则替换所有的 ‘ / ’
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6746270.html
Copyright © 2011-2022 走看看