BZOJ1016: [JSOI2008] Minimum spanning tree count - problem solving

https://www.lydsy.com/JudgeOnline/problem.php?id=1016

A simple undirected weighted graph is now given. You are not satisfied with finding the minimum spanning tree for this graph, you want to know how many different minimum spanning trees there are in this graph. (The two minimum spanning trees are different if at least one of their edges is different). Since there may be many different minimum spanning trees, you only need to output the modulo of the number of solutions to 31011.

There are no more than two: K algorithm and P algorithm (of course there is a third but I won't (funny)

The P algorithm cannot be solved, so the K algorithm is used.

After finding the correctness of the K algorithm, in fact, what we need to do is to find some edges from the K algorithm, which can be replaced by other edges with the same weight and a spanning tree.

So we can enumerate.

(Of course, you will have two questions: 1. Why can the side weights be the same and can be replaced, 2. Does the operation of the front side have any effect on the back side?)

(So ​​if the violent players have no brains, they can easily finish typing the code and leave (such as me))

(Actually there are two theorems, namely:

1. In different minimum spanning trees, the number of edges of each weight is determined.

2. In different spanning trees, after the edge connection of a certain weight is completed, the state of the connected block formed is the same.

Baidu. )

( https://blog.csdn.net/jarily/article/details/8902402 Maybe this explanation is more reliable?)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=101;
const int M=1010;
const int p=31011;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct node{
    int u,v,w;
}e[M];
struct range{
    int l,r;
}a[M];
int fa [N], t [M], n, m, k, sum;
inline bool cmp(node a,node b){
    return a.w<b.w;
}
int find(int x){
    if(fa[x]==x)return x;
    return find(fa[x]);
}
inline void unionn(int x,int y){
    fa [x] = y;
}
inline void destory(int x,int y){
    fa [x] = x; fa [y] = y;
}
void dfs(int l,int r,int d,int w){
    if(l>r){
        if(d==t[w])sum=(sum+1)%p;
        return;
    }
    if(r-l+1+d<t[w])return;
    int u=find(e[l].u),v=find(e[l].v);
    if(u!=v&&d<t[w]){
        unionn (u, v);
        dfs(l+1,r,d+1,w);
        destory(u,v);
    }
    dfs(l+1,r,d,w);
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=m;i++){
        e[i].u=read(),e[i].v=read(),e[i].w=read();
    }
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=n;i++)fa[i]=i;
    int cnt=0;
    for(int i=1;i<=m;i++){
        if(e[i].w!=e[i-1].w){
            a[++k].l=i;a[k-1].r=i-1;
        }
        int u=e[i].u,v=e[i].v;
        u=find(u),v=find(v);
        if(u!=v)t[k]++,cnt++,unionn(u,v);
    }
    a[k].r=m;
    if(cnt!=n-1){
        puts("0");return 0;
    }
    int ans=1;
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=k;i++){
        if(!t[i])continue;
        sum=0;
        dfs(a[i].l,a[i].r,0,i);
        ans=(ll)ans*sum%p;
        for(int j=a[i].l;j<=a[i].r;j++){
            int u=e[j].u,v=e[j].v;
            u =find(u),v= find(v);
            if (u!= v)unionn(u,v);
        }
    }
    printf("%d\n",ans);
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+ Author of this article: luyouqi233. +

+Welcome to my blog: http://www.cnblogs.com/luyouqi233/  +

+++++++++++++++++++++++++++++++++++++++++++

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325317700&siteId=291194637