zoukankan      html  css  js  c++  java
  • Always Online hdu 6350

    ps:今天真是石乐志,改了一下午bug,结果是忘了排序。。。。。。。。。。这题姿势较多,坑点就一个。

    题解:有个结论,任意两点之间如果至多存在两条不相交路径,那么每一条边至多出现在一个环中(very important !)。如果一个s - t割要割掉某个环中的边,那么割掉的边顶多只能是两条,且这个环中最小容量的边一定会被割掉。所以我们可以割掉每个环中的最小容量边,并把其容量加到这个环中的其它边上。这样并不会影响任意两点间的最大流,且把图降为一棵树,而最大流也简化成了两点之间路径上的容量最小的。考虑将容量按降序插入空树中,那么当前要加的边必然是两个联通块A,B的最小割,话句话说,割掉这条边,A,B集合中的点一定不联通,所以这条边的容量就是 u - v 的最大流(u ∈ A, v∈B)。位运算一般都要考虑二进制,算每一位的贡献,所以枚举权重就好了。注意爆long long

    #include<bits/stdc++.h>
    #define ull unsigned long long
    #define ll long long
    #define P pair<int, int>
    #define pb push_back
    #define mp make_pair
    #define pp pop_back
    #define lson root << 1
    #define INF (int)2e9 + 7
    #define rson root << 1 | 1
    #define LINF (unsigned long long int)1e18
    #define sc(x) scanf("%d", &x)
    #define pr(x) printf("%d
    ", x)
    #define mem(arry, in) memset(arry, in, sizeof(arry))
    using namespace std;
    
    inline void upd(int &x, int y) {
        x < y && (x = y);
    }
    
    const int N = 300005;
    
    ull ans, cnt[N][32][2];
    int T, n, m, dep[N], pa[N], fa[N], id[N];
    bool use[N];
    
    struct mode { int u, v, w; } eg[N], sg[N];
    
    inline bool cmp(mode& a, mode& b) {
        return a.w > b.w;
    }
    
    int getFa(int a) {
        return (a == fa[a] ? a : fa[a] = getFa(fa[a]));
    }
    
    bool Union(int a, int b) {
        int x = getFa(a);
        int y = getFa(b);
        if (x != y) {
            fa[x] = y;
            return true;
        }
        return false;
    }
    
    vector<P> g[N];
    
    void Inite() {
        for (int i = 1; i <= n; ++i) {
            g[i].clear();
            for (int j = 0; j < 32; ++j) {
                cnt[i][j][0] = ((i >> j) & 1) ^ 1;
                cnt[i][j][1] = ((i >> j) & 1);
            }
        }
    }
    
    
    void DFS(int u, int p) {
        pa[u] = p;
        for (auto v : g[u]) if (p != v.first) {
            id[v.first] = v.second;
            dep[v.first] = dep[u] + 1;
            DFS(v.first, u);
        }
    }
    
    void change(int u, int v, int w) {
        if (u == v) return;
        if (dep[u] < dep[v]) swap(u, v);
        while (dep[u] != dep[v]) {
            eg[id[u]].w += w;
            u = pa[u];
        }
        while (u != v) {
            eg[id[u]].w += w, eg[id[v]].w += w;
            u = pa[u], v = pa[v];
        }
    }
    
    void compute(int u, int v, int w) {
        u = getFa(u);
        v = getFa(v);
        for (ull i = 0; i < 31; ++i) {
            if (w & (1ull << i)) {
                ans += cnt[u][i][0] * cnt[v][i][0] * (1ull << i);
                ans += cnt[u][i][1] * cnt[v][i][1] * (1ull << i);
            }
            else {
                ans += cnt[u][i][0] * cnt[v][i][1] * (1ull << i);
                ans += cnt[u][i][1] * cnt[v][i][0] * (1ull << i);
            }
        }
        fa[u] = v;
        for (int i = 0; i < 31; ++i) {
            cnt[v][i][0] += cnt[u][i][0];
            cnt[v][i][1] += cnt[u][i][1];
        }
    }
    
    int main()
    {
        //freopen("D:\1001.in","r",stdin);
        //freopen("D:\1.txt","w",stdout);
    
        sc(T);
            while (T--) {
                sc(n), sc(m);
    
                Inite();
                for (int i = 1; i <= m; ++i) {
                    use[i] = 0;
                    scanf("%d %d %d", &eg[i].u, &eg[i].v, &eg[i].w);
                }
    
                sort(eg + 1, eg + m + 1, cmp);
    
                for (int i = 1; i <= n; ++i) fa[i] = i;
                for (int i = 1; i <= m; ++i) if (Union(eg[i].u, eg[i].v)) {
                    use[i] = 1;
                    g[eg[i].u].pb(P(eg[i].v, i));
                    g[eg[i].v].pb(P(eg[i].u, i));
                }
    
                dep[1] = 0;
                DFS(1, -1);
                for (int i = 1; i <= m; ++i) if (!use[i]) change(eg[i].u, eg[i].v, eg[i].w);
    
                int tot = 0;
                for (int i = 1; i <= m; ++i) if (use[i]) sg[++tot] = eg[i];
    
                sort(sg + 1, sg + tot + 1, cmp);  // 一定要重排一道,因为边的权重发生了变化,WA了一下午
    
                ans = 0;
                for (int i = 1; i <= n; ++i) fa[i] = i;
                for (int i = 1; i <= tot; ++i) compute(sg[i].u, sg[i].v, sg[i].w);
    
                printf("%llu
    ", ans);
            }
        return 0;
    }
  • 相关阅读:
    通过日志过滤的方法,统计每天内容详情页面的PV数
    模拟开户接口,使用python脚本实现批量用户开通
    模拟开户接口,使用shell脚本实现批量用户开通
    TCP的socket资源被耗尽的问题
    excel文件使用navicat工具导入mysql的方法
    MYSQL主从同步/主主同步
    django在创建用户时设置一个默认的密码
    django 字段默认值
    django中写入数据时给密码加密
    django后台admin页面表单自定义
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9458019.html
Copyright © 2011-2022 走看看