zoukankan      html  css  js  c++  java
  • HDU4467 Graph【轻重点维护】

    HDU4467 Graph

    题意:

    给出一张染色图,(n)个点每个点是黑色或者白色,(m)条带权边,(q)次操作,有两种操作:

    1. 改变一个点的颜色
    2. 问所有边中两个端点的颜色为给定情况的边权和是多少

    题解:

    首先因为有重边,所以先把重边合并一下
    然后按每个点的度数是否大于(sqrt{边总数}),把点分轻点和重点,同时记录所有三种询问情况的答案
    在图中,重点我们保存其所有连的重点的边,轻点我们保存其所有连出去的边
    显然重点不会超过(sqrt{边总数})个,且重点和轻点所连出去的边不会超过(sqrt{边总数})
    每个重点要记录它连出去的到达黑点的边的总权值和到达白点的边的总权值
    对于每次修改操作,分轻重点分别维护

    • 如果修改的是轻点,那么直接暴力修改答案
    • 如果是重点,利用保存的连出去的边到达的两种颜色的权值和更新答案
      同时每次修改一个点,需要更新其连的重点的两个总权值数据

    对于查询操作直接输出记录的答案即可
    查询复杂度(O(1))
    修改复杂度(O(sqrt{边总数}))
    总时间复杂度为(O(q sqrt{边总数}))
    只给了(32MB)的空间,很容易爆内存

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    typedef long long int LL;
    int n,m,col[MAXN],deg[MAXN];
    LL vtot[3],val[2][MAXN];
    bool heavy[MAXN];
    vector<pair<int,LL>> G[MAXN];
    char op[10];
    void solvequery(){    
        scanf("%s",op);
        if(op[0]=='A'){
            int x, y;
            scanf("%d %d",&x,&y);
            printf("%I64d
    ",vtot[x+y]);
        }
        else{
            int x; scanf("%d",&x);
            if(heavy[x]){
                vtot[1+col[x]] -= val[1][x]; vtot[0+col[x]] -= val[0][x];
                vtot[1+(col[x]^1)] += val[1][x]; vtot[0+(col[x]^1)] += val[0][x];
            }
            else{
                for(auto e : G[x]){
                    vtot[col[x]+col[e.first]] -= e.second;
                    vtot[(col[x]^1)+col[e.first]] += e.second;
                }
            }
            for(auto e : G[x]){
                if(!heavy[e.first]) continue;
                val[col[x]][e.first] -= e.second;
                val[col[x]^1][e.first] += e.second;
            }
            col[x] ^= 1;
        }
    }
    pair<pair<int,int>,LL> vec[MAXN];
    void solve(int kase){
        for(int i = 1; i <= n; i++){
            scanf("%d",&col[i]);
            G[i].clear();
            val[0][i] = val[1][i] = deg[i] = 0;
        }
        vtot[0] = vtot[1] = vtot[2] = 0;
        int tot = 0;
        for(int i = 1; i <= m; i++){
            int u, v, w; scanf("%d %d %d",&u,&v,&w);
            if(u>v) u ^= v ^= u ^= v;
            vec[++tot] = make_pair(make_pair(u,v),w);
        }
        sort(vec+1,vec+1+tot);
        int nt = 1;
        for(int i = 2; i <= tot; i++){
            if(vec[i].first==vec[nt].first) vec[nt].second += vec[i].second;
            else vec[++nt] = vec[i];
        }
        for(int i = 1; i <= nt; i++) deg[vec[i].first.first]++, deg[vec[i].first.second]++;
        int up = sqrt(nt);
        for(int i = 1; i <= n; i++)  heavy[i] = deg[i]>=up;
        for(int i = 1; i <= nt; i++){
            auto &e = vec[i];
            int u = e.first.first, v = e.first.second;
            LL w = e.second;
            if(heavy[u]){
                if(heavy[v]) G[u].push_back(make_pair(v,w));
                val[col[v]][u] += w;
            }
            else G[u].push_back(make_pair(v,w));
            if(heavy[v]){
                if(heavy[u]) G[v].push_back(make_pair(u,w));
                val[col[u]][v] += w;
            }
            else G[v].push_back(make_pair(u,w));
            vtot[col[u]+col[v]] += w;
        }
        int q; scanf("%d",&q);
        printf("Case %d:
    ",kase);
        while(q--) solvequery();
    }
    int main(){
        int kase = 0;
        while(scanf("%d %d",&n,&m)!=EOF) solve(++kase);
        return 0;
    }
    
  • 相关阅读:
    layui 动态设置radio选中
    C# ling 查询 in 用法
    sql 去除小数点后面无效的0
    VUE 全局变量申明和取值
    SQL 逗号分隔将一行拆成多行
    devexpress 延长试用期 licenses.licx
    BugkuCTF-WEB4
    一招破解网页复制+网页上如何实现禁止复制粘贴
    JS的函数
    JS的数组
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12877227.html
Copyright © 2011-2022 走看看