JSOI 2008最小スパニングツリーカウント問題の解決策

トピックポータル

トピックの主なアイデア:グラフにはいくつの最小全域木がありますか?

回答

最小全域木にはプロパティがあります。つまり、各長さのエッジの数は固定されています。

したがって、最初に最小全域木を見つけ、長さをiiと見なしますiの辺については、最初に長さをii以外に変更しますiの最小スパニングツリーのエッジが追加され、次にいくつかの接続されたブロックが形成されます。残りの問題は、iiの長さを使用することです。明らかに、行列ツリーの定理は、 iのエッジがこれらの接続されたブロックをツリーに接続するためにいくつのスキームがあるかを見つけるために使用できます。

最後に、各長さの計画数を乗算することが答えです。

コードは以下のように表示されます:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 110
#define mod 31011

int n,m,ans=1;
struct edge{
    
    int x,y,z;}e[1010];
int belong[maxn];bool v[1010];
struct BCJ{
    
    
	int fa[maxn];
	void init(){
    
    for(int i=1;i<=n;i++)fa[i]=i;}
	int findfa(int x){
    
    return x==fa[x]?x:fa[x]=findfa(fa[x]);}
	bool linked(int x,int y){
    
    return findfa(x)==findfa(y);}
	bool link(int x,int y)
	{
    
    
		x=findfa(x),y=findfa(y);
		if(x==y)return false;
		fa[y]=x;return true;
	}
}F;
bool cmp(edge x,edge y){
    
    return x.z<y.z;}
int dec(int x){
    
    return x<0?x+mod:x;}
int f[maxn][maxn];int det(int l)
{
    
    
	int re=1,fu=1;
	for(int i=1,p;i<=l;i++)
	{
    
    
		for(int j=i+1;j<=l;j++)
		while(f[j][i]!=0){
    
    
			p=f[i][i]/f[j][i];
			for(int k=i;k<=l;k++)f[i][k]=f[i][k]-f[j][k]*p;
			swap(f[i],f[j]); fu=-fu;
		}
		re=1ll*re*f[i][i]%mod;
	}
	return re*fu;
}

int main()
{
    
    
	scanf("%d %d",&n,&m);for(int i=1;i<=m;i++)
	scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].z);sort(e+1,e+m+1,cmp);
	F.init();for(int i=1;i<=m;i++)if(F.link(e[i].x,e[i].y))v[i]=true;
	for(int i=2;i<=n;i++)if(F.findfa(i)!=F.findfa(1))return printf("0"),0; 
	int now=1;while(now<=m)
	{
    
    
		bool con=false;int to=now;for(;e[to].z==e[now].z&&to<=m;to++)con|=v[to];if(!con){
    
    now=to;continue;}
		F.init();for(int i=1;i<=m;i++)if(v[i]&&e[i].z!=e[now].z)F.link(e[i].x,e[i].y);
		int id=0;memset(belong,0,sizeof(belong));memset(f,0,sizeof(f));
		for(int i=1;i<=n;i++)if(F.fa[i]==i)belong[i]=++id;
		for(int i=1;i<=n;i++)belong[i]=belong[F.findfa(i)];
		for(int i=now;i<to;i++){
    
    
			int x=belong[e[i].x],y=belong[e[i].y];
			f[x][y]--,f[y][x]--,f[x][x]++,f[y][y]++;
		}
		ans=1ll*ans*det(id-1)%mod;now=to;
	}
	printf("%d",ans);
}

おすすめ

転載: blog.csdn.net/a_forever_dream/article/details/107364468
おすすめ