BZOJ4596: [SHOI2016] Gensokyo Before Darkness - Problem Solving

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

https://www.luogu.org/problemnew/show/P4336#sub

The four-yearly Gensokyo General Election has begun. The biggest problem in Gensokyo recently is that many monsters of unknown origin have poured into Gensokyo, disrupting the old order of Gensokyo. However, the establishment monsters (human beings) of Gensokyo Hakurei Reimu and Yakumo Zi and others talk all day long about the equality of all monsters, the diversity of Gensokyo, and so on. solution.
Yuka Kazama is one of the few big monsters in Gensokyo who realizes the seriousness of the problem. She bravely stood up this time to participate in the Gensokyo general election. He proposed a series of plans, including building a wall on the border of Gensokyo (and asking humans to pay), vigorously developing infrastructure to restore unemployment, etc., and became an unexpected dark horse in the election year and successfully became the commander of Gensokyo.
 
After Yuxiang came to power, the first measure was to build a highway in Gensokyo. Gensokyo has N cities, and there are no roads between them. Yuka promises voters to cut taxes, so she plans to build only N-1 roads to connect the cities. But Gensokyo has exactly N- 1 construction companies, and each construction company wants to gain something in the process of building the road. Although these construction companies did not give Youxiang money before the election, Youxiang still planned to have a good relationship with them, because she also counted on them to help her build the wall. So she plans to make each construction company responsible for a road to be repaired.
 
Each construction company told Youxiang which cities she was able to build the roads between. So Yuka plans to choose N-1 edges that can connect all the cities in Gensokyo, and then hand over each edge to a construction company that can be responsible for the edge, and each construction company will repair exactly one edge.
 
Yuxiang now wants to know how many possible solutions are there? Two schemes are different if and only if they either have different sets of trimmed edges, or different ways of assigning edges.

After reading the matrix tree tutorial it let me do this question http://www.cnblogs.com/zj75211/p/8039443.html .

I feel very old.

n<=17 is obviously about to press the state, then we can only press whether to choose each company to build the side... It seems that it does not match the meaning of the question.

But thinking, in fact what we ask for can be expressed by inclusion and exclusion, i.e. (regardless of which companies build which edges) I add the number of solutions for all companies' edges - I subtract the number of solutions for all edges of one company +... In the end, all illegal schemes were eliminated anyway.

Then we enumerate the states, use the matrix tree theorem to find the number of spanning trees is the solution, and then add and subtract.

#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
#include<cctype>
#include<algorithm>
using namespace std;
typedef long long ll;
const int p=1e9+7;
const int N=18;
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;
}
ll x[N][N],ans;
ll gauss(int n){
    ll res=1;
    for(int i=1;i<=n;i++){
    for(int j=i+1;j<=n;j++){
        while(x[j][i]!=0){
        ll t=x[i][i]/x[j][i];
        for(int k=i;k<=n;k++)x[i][k]=(x[i][k]-x[j][k]*t)%p;
        for(int k=i;k<=n;k++)swap(x[i][k],x[j][k]);
        res = - res;
        }
    }
    if(!x[i][i])return 0;
    res=(res*x[i][i])%p;
    }
    return (res%p+p)%p;
}
int n,m[N],u[N][N*N],v[N][N*N],d[N];
int main(){
    n=read();
    for(int i=1;i<n;i++){
    m[i]=read();
    for(int j=1;j<=m[i];j++){
        u[i][j]=read(),v[i][j]=read();
    }
    }
    for(int i=(1<<(n-1))-1;i>=0;i--){
    int tot=0;
    memset(x,0,sizeof(x));
    memset(d,0,sizeof(d));
    for(int j=1;j<n;j++){
        int w=(i>>(j-1))&1;
        if(w){
        for(int k=1;k<=m[j];k++){
            x[u[j][k]][v[j][k]]--;
            x[v[j][k]][u[j][k]]--;
            d[u[j][k]]++;d[v[j][k]]++;
        }
        for(int k=1;k<=n;k++)x[k][k]=d[k];
        to ++ ;
        }
    }
    ll tmp=gauss(n-1);
    if((n-1-tot)%2==0)ans=(ans+tmp)%p;
    else ans=(ans-tmp)%p;
    }
    printf("%lld\n",(ans%p+p)%p);
    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=325140264&siteId=291194637