[HDU - 6350] Always Online

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013578420/article/details/82461160

题目链接

https://vjudge.net/contest/252211#problem/A

题目大意

T组数据 ( T 100 ) , 给出一个n个点m条边的无向图 ( 1 n 10 5 , n 1 m 3 2 ( n 1 ) ) , 每条边有容量 w i ( 1 w i 10 9 ) , 图中最多存在两条完全不相交的路径,图连通, 无自环重边。求 s < t s t f l o w ( s , t ) ( n 10 6 )

题目思路

最多存在两条完全不相交的路径等价于每条边最多属于一个环上。
最大流等于最小割, 考虑割边。
由原图特性, s->t的路径构成为若干个环和一些边。
对于一个简单环, 割边一定是个其中两条边, 且一定包含环上最小的那条边。
对于若干个环加一些边组合在一起, 割边一定是某个环上的两条边或是一条单独的非环边。
将环上的边作特殊处理, 考虑到如果要割的话最小的那条边一定被割, 所以将每个环删去最小边, 将容量加在环上的其他边的上, 不会影响答案。
最后留下一棵树, 考虑从大到小加入每条边, 则新连通的这两个集合之间的最小割即为这条边的容量, 用并查集维护集合中每个二进制位为1的个数, 每次合并之前计算一次贡献即可。

Code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>

#define ll long long
#define ull unsigned ll 

using namespace std;

const int N = (int)1e5 + 10;
const int M = (int)1e6 + 10;

int n, m;
int cnt, lst[N], nxt[M], to[M], edg[M][3], id[M], del[M];
int gi(){
    char c = getchar(); int ret = 0;
    while (!isdigit(c)) c = getchar();
    while (isdigit(c)){
        ret = ret * 10 + c - '0';
        c = getchar();
    }
    return ret;
}
void add(int u, int v, int c){
    nxt[++ cnt] = lst[u]; lst[u] = cnt; to[cnt] = v;
    nxt[++ cnt] = lst[v]; lst[v] = cnt; to[cnt] = u; 
}

int indx, pre[N], dfn[N]; bool vis[N];
void dfs(int u, int pid){
    vis[u] = 1; dfn[u] = ++ indx;
    for (int j = lst[u]; j; j = nxt[j]){
        if (pid == (j / 2)) continue;
        int v = to[j];
        if (!vis[v]) {pre[v] = j; dfs(v, j / 2);}
        else if(dfn[v] < dfn[u]){
            int wid = j / 2;
            for (int p = u; p != v; p = to[pre[p] ^ 1]){
                int k = pre[p] / 2;
                if (edg[wid][2] > edg[k][2]) wid = k;
            }
            del[wid] = 1;
            for (int p = u; p != v; p = to[pre[p] ^ 1]){
                int k = pre[p] / 2;
                if (k == wid) continue;
                edg[k][2] += edg[wid][2];
            }
            if (j / 2 != wid){
                if (j / 2 != wid){
                    edg[j / 2][2] += edg[wid][2];
                }
            }
        }
    }
}

int fa[N], bit[N][30], sz[N];
int find(int x){
    if (fa[x] == x) return x;
    return fa[x] = find(fa[x]);
}
void unit(int r1, int r2){
    r1 = find(r1), r2 = find(r2);
    if (r1 != r2){
        fa[r1] = r2;
        for (int j = 0; j < 20; j ++)
            bit[r2][j] += bit[r1][j];
        sz[r2] += sz[r1];
    }
}
bool cmp(int i, int j){return edg[i][2] > edg[j][2];}

int main()
{

    int T = gi();
    while (T --){
        n = gi(), m = gi();
        cnt = 1;

        for (int i = 1, u, v, c; i <= m; i ++){
            u = gi(), v = gi(), c = gi();
            add(u, v, c);
            edg[i][0] = u, edg[i][1] = v; edg[i][2] = c;
        }

        dfs(1, 0);
        for (int i = 1; i <= m; i ++) id[i] = i;
        for (int i = 1; i <= n; i ++){
            fa[i] = i;
            for (int j = 0; j < 20; j ++) bit[i][j] = (i >> j) & 1;
            sz[i] = 1;
        }

        sort(id + 1, id + m + 1, cmp);
        ull ans = 0;

        for (int iid = 1; iid <= m; iid ++){
            int i = id[iid];
            if (del[i]) continue;
            int u = edg[i][0], v = edg[i][1];
            u = find(u), v = find(v);
            if (u != v){
                int w = edg[i][2];
                for (int j = 0; j < 20; j ++){
                    if ((w >> j) & 1){
                        ans += (ull)bit[u][j] * bit[v][j] * (1 << j);
                        ans += (ull)(sz[u] - bit[u][j]) * (sz[v] - bit[v][j]) * (1 << j);
                    }
                    else{
                        ans += (ull)(sz[u] - bit[u][j]) * bit[v][j] * (1 << j);
                        ans += (ull)bit[u][j] * (sz[v] - bit[v][j]) * (1 << j);
                    }
                }
                ans += (ull)(w >> 20) * sz[u] * sz[v] * (1 << 20);
                unit(u, v);
            }
        }

        printf("%llu\n", ans);

        for (int i = 1; i <= n; i ++) lst[i] = 0, pre[i] = 0, vis[i] = 0;
        for (int i = 1; i <= m; i ++) del[i] = 0;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u013578420/article/details/82461160
今日推荐