UVA 10766 Organising the Organisation 生成树计数

66 篇文章 0 订阅


生成树计数: 基尔霍夫矩阵树定理


无向图的基尔霍夫矩阵: 对角线上表示每个点的度数,若ij之间有边则矩阵ij处为-1

无向图的生成树的数目为: 任意一个n-1阶主子式的行列式的绝对值.



UVA - 10766
Time Limit: 3000MSMemory Limit: Unknown64bit IO Format: %lld & %llu

Submit Status

Description

Download as PDF

Problem H
Organising the Organisation

Input: Standard Input

Output: Standard Output

Time Limit: 2 Second

 

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 manydifferent 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, 0 ≤ m ≤ 1500, 1 ≤ k ≤ n)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 mlines, 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.

 

Sample Input                               Output for Sample Input

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

3

 



Problem setter: Per Austrin

Source

Root :: Prominent Problemsetters ::  Per Austrin
Root :: AOAPC II: Beginning Algorithm Contests (Second Edition) (Rujia Liu) :: Chapter 12. Advanced Topics ::  Extra

Submit Status




/* ***********************************************
Author        :CKboss
Created Time  :2015年04月28日 星期二 16时20分58秒
File Name     :UVA10766.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

typedef long double LD;

const LD eps=1e-10;

const int maxn=60;

int sgn(LD x)
{
	if(fabs(x)<eps) return 0; if(x<0) return -1; return 1;
}

LD b[maxn][maxn];

LD det(LD a[][maxn],int n)
{
	int sign=0;
	int i,j,k;
	LD ret=1;
	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
			b[i][j]=a[i][j];
	for(i=0;i<n;i++)
	{
		if(sgn(b[i][i])==0)
		{
			for(j=i+1;j<n;j++)
				if(sgn(b[j][i])!=0)
					break;
			if(j==n) return 0;
			for(k=i;k<n;k++)
				swap(b[i][k],b[j][k]);
			sign++;
		}
		ret*=b[i][i];
		for(k=i+1;k<n;k++)
			b[i][k]/=b[i][i];
		for(j=i+1;j<n;j++)
			for(k=i+1;k<n;k++)
				b[j][k]-=b[j][i]*b[i][k];
	}
	if(sign&1) ret=-ret;
	return ret;
}

bool g[maxn][maxn];
LD a[maxn][maxn];
int n,m,k;

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

	while(scanf("%d%d%d",&n,&m,&k)!=EOF)
	{
		memset(g,true,sizeof(g));
		memset(a,0,sizeof(a));

		for(int i=0;i<m;i++)
		{
			int x,y; scanf("%d%d",&x,&y);
			x--; y--;
			g[x][y]=g[y][x]=false;
		}

		for(int i=0;i<n;i++)
		{
			for(int j=i+1;j<n;j++)
			{
				if(g[i][j]==true)
				{
					a[i][i]++; a[j][j]++;
					a[i][j]=-1; a[j][i]=-1;
				}
			}
		}

		LD ans=det(a,n-1);
		printf("%.0Lf\n",ans);
	}
    
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值