洛谷4455 [CQOI2018]社交网络 (有向图矩阵树定理)(学习笔记)

sro_ptx_orz

qwq算是一个套路的记录

对于一个有向图来说

如果你要求一个外向生成树的话,那么如果存在一个 u → r u\rightarrow r ur的边
那么 a [ u ] [ v ] − − , a [ v ] [ v ] + + a[u][v]--,a[v][v]++ a[u][v],a[v][v]++

对应的去掉第 i i i行和第 i i i列的余子式,就是以 i i i为根的生成树个数。

内向生成树也是同理。所有的反过来即可

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk make_pair
#define ll long long
//#define int long long
#define rint register int
using namespace std;
inline int read()
{
  int x=0,f=1;char ch=getchar();
  while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
  while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}
const int maxn = 310; 
const int mod = 10007;
int qsm(int i,int j)
{
	int ans=1;
	while (j)
	{
		if (j&1) ans=ans*i%mod;
		i=i*i%mod;
		j>>=1;
	}
	return ans;
}
int a[maxn][maxn];
int n,m;
int d[maxn][maxn];
int b[maxn][maxn];
void gauss()
{
	int k=1;
	int ff=1;
	int ans=1;
	for (rint i=1;i<=n;++i)
	{
		int now = k;
		while (now<=n && !(a[now][i])) ++now;
		if (now==n+1) continue;
		if (now!=k) ff*=-1;
		for (rint j=1;j<=n;++j) swap(a[now][j],a[k][j]);
		int inv = qsm(a[k][i],mod-2);
        for (rint j=i+1;j<=n;++j)
		{
			int t = a[j][i]*inv%mod;
			for (rint p=1;p<=n;++p) a[j][p]=(a[j][p]-a[k][p]*t%mod+mod)%mod;
		}
		++k;
	}
	for (rint i=1;i<=n;++i) ans=ans*a[i][i]%mod;
	if(ff==-1) cout<<mod-ans;
	else cout<<ans;
}
signed main()
{
  n=read(),m=read();
  for (rint i=1;i<=m;++i)
  {
  	int x=read(),y=read();
  	a[x][x]++;
  	a[y][x]--;
  }
  for (rint i=1;i<=n;++i)
    for (rint j=1;j<=n;++j) b[i][j]=a[i][j];
  for (rint i=1;i<n;++i)
    for (rint j=1;j<n;++j)
    {
    	a[i][j]=b[i+1][j+1];
	}
  n--;
  gauss(); 
  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值