我是靠谱客的博主 甜美小海豚,最近开发中收集的这篇文章主要介绍UVA10766:Organising the Organisation(生成树计数),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Organising the Organisation

题目链接:https://vjudge.net/problem/UVA-10766

Description:

I am the chief of the Personnel Division of a moderate-sized company that wishes to remain anonymous, and I am currently facing a small problem for which I need a skilled programmer’s help. Currently, our company is divided into several more or less independent divisions. In order to make our business more efficient, these need to be organised in a hierarchy, indicating which divisions are in charge of other divisions. For instance, if there are four divisions A, B, C and D we could organise them as in Figure 1, with division A controlling divisions B and D, and division D controlling division C. One of the divisions is Central Management (division A in the figure above), and should of course be at the top of the hierarchy, but the relative importance of the remaining divisions is not determined, so in Figure 1 above, division C and D could equally well have switched places so that C was in charge over division D. One complication, however, is that it may be impossible to get some divisions to cooperate with each other, and in such a case, neither of these divisions can be directly in charge of the other. For instance, if in the example above A and D are unable to cooperate, Figure 1 is not a valid way to organise the company. In general, there can of course be many different ways to organise the organisation, and thus it is desirable to find the best one (for instance, it is not a good idea to let the programming people be in charge of the marketing people). This job, however, is way too complicated for you, and your job is simply to help us find out how much to pay the consultant that we hire to find the best organisation for us. In order to determine the consultant’s pay, we need to find out exactly how difficult the task is, which is why you have to count exactly how many different ways there are to organise the organisation. Oh, and I need the answer in five hours.

Input:

The input consists of a series of test cases, at most 50, terminated by end-of-file. Each test cases begins with three integers n, m, k (1 ≤ n ≤ 50, 1 ≤ m ≤ n, 0 ≤ k ≤ 1500). n denotes the number of divisions in the company (for convenience, the divisions are numbered from 1 to n), and k indicates which division is the Central Management division. This is followed by m lines, each containing two integers 1 ≤ i, j ≤ n, indicating that division i and division j cannot cooperate (thus, i cannot be directly in charge of j and j cannot be directly in charge of i). You may assume that i and j are always different.

Output:

For each test case, print the number of possible ways to organise the company on a line by itself. This number will be at least 1 and at most 1015 . Note: The three possible hierarchies in the first sample case

Sample Input:

5 5 2 3 1 3 4 4 5 1 4 5 3 4 1 1 1 4 3 0 2

Sample Output:

3 8 3

题意:

给出n个点,然后一个主结点k,之后给出m个关系,每个关系会输入u,v,表示这两个点不能直接相连。最后问总方案数为多少。

 

题解:

生成树计数模板题,主要是Matrix-Tree定理,我现在还不会证...但是对于这类题知道就好了吧?

之后构造基尔霍夫矩阵就行了,就是度数矩阵 - 邻接矩阵。

然后用类似于高斯消元的方法去求解n-1阶行列式,最后主对角线的乘积就是答案。

具体见代码吧:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 55;
ll b[N][N];
int g[N][N];
int n,m,k;
ll Det(int n){
    int i,j,k;
    ll ret = 1;
    for(i=2;i<=n;i++){
        for(j = i+1;j <= n;j++){
            while(b[j][i]){  
                ll tmp=b[i][i]/b[j][i];
                for(k = i;k <= n;k++)
                    b[i][k] -= tmp*b[j][k];
                for(k=i;k<=n;k++)
                    swap(b[i][k],b[j][k]); 
                ret = -ret; //行列式性质
            }
        }
        if(!b[i][i]) return 0;
        ret *= b[i][i];
    }
    if(ret < 0) ret = -ret;
    return ret;
}
int main(){
    while(scanf("%d%d%d",&n,&m,&k)!=EOF){
        memset(b,0,sizeof(b));
        memset(g,0,sizeof(g));
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            if(u==v) continue ;
            g[u][v]=g[v][u]=1;//考虑重边
        }
        for(int i=1;i<=n;i++){
            b[i][i]=n-1;
            for(int j=1;j<=n;j++){
                if(i==j) continue ;
                b[i][j]=-1;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(g[i][j]){
                    b[i][i]--;
                    b[i][j]=b[j][i]=0;
                }
            }
        }
        printf("%lldn",Det(n));
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/heyuhhh/p/10392703.html

最后

以上就是甜美小海豚为你收集整理的UVA10766:Organising the Organisation(生成树计数)的全部内容,希望文章能够帮你解决UVA10766:Organising the Organisation(生成树计数)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部