• HDU6832 A Very Easy Graph Problem(最小生成树)


    Problem Description

    An undirected connected graph has n n nodes and m m edges, The i -th edge’s length is (2^i), Each node i has a value (a_i) , which is either 0 or 1. You need to calculate:

    (Sigma^n_{i=1}Sigma^n_{j=1}d(i,j) imes[a_i=1 ∧ a_j=0])

    d(i,j) indicates the shortest distance between i and j . [ ] is the Iverson bracket. ∧ indicates AND. Because the answer may be too large, please output the answer modulo (10^9+7).

    Input

    The first line contains one integer T(1≤T≤8),indicating the number of test cases.

    The second line contains two ingeters n,m(1≤n(10^5),1≤m(2 imes10^5)).

    The third line contains n positive integers a1,a2,...,(a_n)((a_i)=0 or 1) —— the value of the nodes.

    The following m lines contain two ingeters u,v(1≤u,vn), and the i-th line represents the i-th undirected edge’s length is 2i, between node u and v.

    The sum of n,m is no more than 2×(10^5).

    Output

    Print a single integer—— the value of the answer modulo 109+7.

    Sample Input

    1

    3 2

    0 1 0

    3 1

    3 2

    Sample Output

    10

    关键就是要注意到边权的特殊性...

    题目要求所有白点和黑点最短路的值。
    每条边的权值是(2^i),我们可以发现对于第(i)条边,(2^1+2^2+...+2^{i-1}<2^i),所以如果两个点能通过(i-1)条边到达,那肯定比通过第(i)条更优,所以我们从(1)(n)按顺序建最小生成树。

    对于白点和黑点的最短路,我们枚举每条边会被多少种白点和黑点通过,统计两侧的黑白点个数,计算贡献即可。

    看到有大佬写的点分治:https://blog.csdn.net/weixin_44282912/article/details/107849300

    以及奇奇怪怪的树状数组维护:https://blog.csdn.net/leoxe/article/details/107844387

    也是很巧妙的思路。

    #include <bits/stdc++.h>
    #define N 100005
    #define M 200005
    #define ll long long
    using namespace std;
    const ll mod = 1e9+7;
    int n, m, tot = 0, tot0, tot1, head[N], ver[2 * M], Next[2 * M], fa[N], a[N];//tot0和tot1为总的0和1的个数 
    int zero[N], size[N];//zero[i]表示i为根的子树里0的个数 (包括自己) 1的个数可以用size减出来 
    long long ans = 0;
    ll edge[2 * M];
    void add(int x, int y, ll z)
    {
    	ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
    }
    int get(int x)
    {
    	if(x == fa[x]) return x;
    	return (fa[x] = get(fa[x]));
    }
    int dfs0(int x, int pre)
    {
    	size[x] = 1;
    	for(int i = head[x]; i; i = Next[i])
    	{
    		int y = ver[i];
    		if(y == pre) continue;
    		size[x] += dfs0(y, x);
    	}
    	return size[x];
    }
    int dfs1(int x, int pre)
    {
    	if(a[x] == 0) zero[x] = 1;
    	else zero[x] = 0;
    	for(int i = head[x]; i; i = Next[i])
    	{
    		int y = ver[i];
    		if(y == pre) continue;
    		zero[x] += dfs1(y, x);
    	}
    	return zero[x];
    }
    void dfs(int x, int pre)
    {
    	for(int i = head[x]; i; i = Next[i])
    	{
    		int y = ver[i];
    		ll z = edge[i];
    		if(y == pre) continue;
    		int up0 = tot0 - zero[y];
    		int up1 = tot1 - (size[y] - zero[y]);
    		ans = (ans + z * (zero[y] * up1 % mod) % mod ) % mod;
    		ans = (ans +  z * (size[y] - zero[y]) % mod * up0 % mod ) % mod;
    		dfs(y, x);
    	}
    }
    signed main()
    {
    	//freopen("1.in","r",stdin);
    	//freopen("my.out","w",stdout);
    	int t;
    	cin >> t;
    	while(t--)
    	{
    		tot = tot0 = tot1 = 0;
    		memset(head, 0, sizeof(head));
    		memset(zero, 0, sizeof(zero));
    		memset(size, 0, sizeof(size));
    	 	ans = 0;
    		cin >> n >> m;
    		for(int i = 1; i <= n; i++)
    		{
    			cin >> a[i];
    			if(a[i] == 0) tot0++;
    			else tot1++; 
    			fa[i] = i;
    		}
    		ll val = 1;
    		for(int i = 1; i <= m; i++)
    		{
    			int x, y;
    			cin >> x >> y;
    			val = val * 2 % mod;
    			int xx = get(x), yy = get(y);
    			if(xx == yy) continue;
    			fa[xx] = yy;//!!
    			add(x, y, val);
    			add(y, x, val);
    		}
    		dfs0(1, 0);
    		dfs1(1, 0);
    		dfs(1, 0);
    		cout << ans << endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    陪伴
    休假
    I'm back
    Mysql程序
    Mysql 行转列
    Struts2 设置--Myelipse
    struts2 严重: Error filterStart 原因
    廉价药
    在linux下用tomcat部署java web项目的过程与注意事项
    创建表格式
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/13449962.html
Copyright © 2020-2023  润新知