题意:
给出n,m,k,n,m,k,代表一家公司有nn个部门,有mm组关系,表示ii和jj不能直接联通,kk代表主管部门,询问有多少种分层方案
题解:
首先题面看不大懂,直接找到前辈的题目描述Ctrl+C一下
其次,这道题的k可以忽略掉,所以ta的范围完全是吓唬人的
那么这道题就是求nn个点的有编号无根树数量
有编号无根树的一种有力的解决方法就是Prufer编码
但是有些边是不允许出现的
如果我们把可以有的边在图中连上,得到一个图GG
题目就转化成了GG的生成树个数
tip
记录一下交换次数,如果是奇数次,最后答案要乘上符号(当然你直接取绝对值就没这么多事了)
对精度要求比较高,开LD
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define ll long long
#define LD long double
using namespace std;
const int N=55;
const double eps=1e-7;
int n,m,K;
LD a[N][N],d[N][N];
ll gauss(int n) {
int now=1,to;
for (int i=1;i<=n;i++) {
for (to=now;to<=n;to++)
if (fabs(a[to][i])>eps) break;
if (to>n) return 0;
if (to!=now)
for (int i=1;i<=n;i++)
swap(a[to][i],a[now][i]);
for (int j=1;j<=n;j++)
if (j!=now&&fabs(a[j][i])>eps) {
LD t=a[j][i]/a[now][i];
for (int k=1;k<=n;k++)
a[j][k]-=t*a[now][k];
}
now++;
}
LD ans=1;
for (int i=1;i<=n;i++) ans*=a[i][i];
ans=fabs(ans);
printf("%.0lf\n",(double)ans);
}
int main()
{
while (scanf("%d%d%d",&n,&m,&K)!=EOF) {
memset(d,0,sizeof(d));
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++) {
if (i!=j) a[i][j]=1.0;
else a[i][i]=0;
}
for (int i=1;i<=m;i++) {
int x,y;
scanf("%d%d",&x,&y);
a[x][y]=a[y][x]=0;
}
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
if (a[i][j]) d[i][i]++,d[j][j]++;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
a[i][j]=d[i][j]-a[i][j];
gauss(n-1);
}
return 0;
}