ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Rikka with Minimum Spanning Trees徐州区域赛a题

2019-03-03 14:49:30  阅读:478  来源: 互联网

标签:10 graph number long unsigned k2 Minimum Trees Spanning


Hello everyone! I am your old friend Rikka. Welcome to Xuzhou. This is the first problem, which is a problem about the minimum spanning tree (MST). I promise you all that this should be the \textbf{easiest problem}easiest problem for most people.

A minimum spanning tree, or minimum weight spanning tree, is a subset of edges from an edge-weighted undirected graph, which forms a tree with the minimum possible total edge weight that connects all the vertices together without any cycles.

In this problem, Rikka wants you to calculate the summation of total edge weights through all MSTs for a given graph, which obviously equals to the product of the total edge weight in an MST and the total number of different MSTs. Note that two spanning trees are different if the sets of their edges are different. In addition, a disconnected graph could have no MSTs, the number of whose different MSTs is zero.

To decrease the size of the input, Rikka provides an edge-weighted undirected graph via a random number generator with given random seeds, denoted by two integers k_1k
1

and k_2k
2

. Supposing the number of vertices and edges in the graph are nn and mm respectively, the following code in C++ tells you how to generate the graph and store the ii-th edge between the vertex u[i]u[i] and v[i]v[i] with weight w[i]w[i] in corresponding arrays. You can use the code directly in your submissions.

1
unsigned long long k1, k2;
2

3
unsigned long long xorShift128Plus() {
4
unsigned long long k3 = k1, k4 = k2;
5
k1 = k4;
6
k3 ^= k3 << 23;
7
k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
8
return k2 + k4;
9
}
10

11
int n, m, u[100001], v[100001];
12
unsigned long long w[100001];
13

14
void gen() {
15
scanf("%d%d%llu%llu", &n, &m, &k1, &k2);
16
for(int i = 1; i <= m; ++i) {
17
u[i] = xorShift128Plus() % n + 1;
18
v[i] = xorShift128Plus() % n + 1;
19
w[i] = xorShift128Plus();
20
}
21
}
Also, to decrease the size of the output, your code should output the answer modulo (10^9 + 7)(10
9
+7).

\textbf{If you have already learned how to handle that,}If you have already learned how to handle that, \textbf{start your show and omit all the rest of the statement.}start your show and omit all the rest of the statement.

To make sure everyone knows how to solve this problem, here Rikka would like to provide for you all an effective practice which can solve the problem and help you all get Accepted!

The first one you need to know is the Kirchhoff’s matrix tree theorem. Given an undirected graph GG with nn vertices excluding all loops, its Laplacian matrix L_{n \times n}L
n×n

is defined as (D - A)(D−A), where DD is the degree matrix and AA is the adjacency matrix of the graph. More precisely, in the matrix LL the entry l_{i, j}l
i,j

(i \ne ji


=j) equals to -m−m where mm is the number of edges between the ii-th vertex and the jj-th vertex, and L_{i, i}L
i,i

equals to the degree of the ii-th vertex. Next, construct a matrix L^{\ast}L

by deleting any row and any column from LL, for example, deleting row 11 and column 11. The Kirchhoff’s matrix tree theorem shows that the number of spanning trees is exactly the determinant of L^{\ast}L

, which can be computed in polynomial time.

Now let me explain an algorithm that counts the number of MSTs. The algorithm breaks up the Kruskal’s algorithm for MST into a series of blocks, each of which consists of a sequence of operations about adding edges in a same weight into a multigraph (where a multigraph is a graph, two vertices of which may be connected by more than one edge) whose vertices are components that have been built through the previous block of operations.

Precisely speaking, let’s label the multigraph that has been built after the ii-th block of operations as G_iG
i

. Without loss of generality, let’s consider the 00-th block which has no operation and let G_0G
0

be an empty graph with nn isolated vertices. The ii-th block of operations squeezes vertices in G_{i - 1}G
i−1

connected by edges in this block into a single vertex. The result is exactly the graph G_iG
i

.

If you know the cardinal principle of Kruskal’s algorithm pretty well, you may find that the number of MSTs is the product of the numbers of spanning trees in every component of the graph for each block-defining weight. Actually, the number of edges for a certain weight is fixed in all MSTs, based on the greedy-choice strategy in Kruskal’s algorithm. Finally, the Kirchhoff’s matrix tree theorem helps you compute the numbers of spanning trees for graphs.

Input
The input contains several test cases, and the first line contains a single integer TT (1 \le T \le 1001≤T≤100), the number of test cases.

For each test case, the only line contains four integers nn (1 \le n \le 10^5)(1≤n≤10
5
), mm (m = 10^5m=10
5
), k_1k
1

and k_2k
2

(10^8 \le k_1, k_2 \le 10^{12}10
8
≤k
1

,k
2

≤10
12
), where k_1k
1

and k_2k
2

are chosen randomly except for the sample.

Output
For each test case, output a single line with a single number, the answer modulo (10^9 + 7)(10
9
+7).

Note
Since the generator code is only provided for C++, Rikka strongly suggests you all solve the problem using C or C++ instead of other programming languages.

样例输入 复制
1
2 100000 123456789 987654321
样例输出 复制
575673759

由于随机数范围很大 而能生成两个等效边的概率十分微小
所以直接用kruskal水过
补完最小生成树计数原理回来填个坑

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
int father[100005];
unsigned long long mod=1e9+7;
unsigned long long k1,k2;
unsigned long long ran()
{
    unsigned long long k3=k1,k4=k2;
    k1=k4;
    k3^=k3<<23;
    k2=k3^k4^(k3>>17)^(k4>>26);
    return k2+k4;
}
struct node
{
    int u,v;
    unsigned long long w;
}edge[100001];
int n,m;
void gen()
{
    scanf("%d%d%llu%llu",&n,&m,&k1,&k2);
    for(int i=1;i<=m;i++)
    {
        edge[i].u=ran()%n+1;
        edge[i].v=ran()%n+1;
        edge[i].w=ran();
    }
}
int cmp(node a,node b)
{
    return a.w<b.w;
}
int fi(int x)
{
    if(father[x]==x) return x;
    return father[x]=fi(father[x]);
}
int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        gen();
        unsigned long long ans=0;
        int cnt=0;
        sort(edge+1,edge+1+m,cmp);
        for(int i=1;i<=m;i++)father[i]=i;
        for(int i=1;i<=m;i++)
        {
            if(fi(edge[i].u)!=fi(edge[i].v))
            {
                father[fi(edge[i].u)]=fi(edge[i].v);
                ans=(ans+edge[i].w)%mod;
                cnt++;
            }
        }
        if(cnt!=n-1) printf("0\n");
        else printf("%llu\n",ans);

    }

}

标签:10,graph,number,long,unsigned,k2,Minimum,Trees,Spanning
来源: https://blog.csdn.net/caowenbo2311694605/article/details/88088118

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有