【XSY3163】Tree Ext【二分】【最小生成树】【矩阵树定理】【拉格朗日插值】

给一张 n 个点 m 条边的无向连通图,每条边是黑边或白边 ,有边权。问有多少棵恰好有k条白边,且在此前提下边权和最小的生成树。mod 1e9+7。
首先看一看这道题。
ACM Live Archieve 7138
这里有一个良心的题解。
题解
这里写图片描述
对于恰好k条白边的要求,我们可以二分一个权,给每条白边加上这个权,再最小生成树,注意相同边权白边排前面,如果最小生成树中白边数量>=k判定为可行,否则判定为不可行。
这不就是bzoj2654吗?
最后这题要求的是最小生成树计数,不是生成树计数。不过我们可以通过乘法原理和分段的思想转化为多次生成树计数。这不就是bzoj1016吗?
因为某些玄学bug一直WA30分QAQ
注意可能相同边权的边全部连了之后,各个联通块仍然不连通,所以要提前在他们之间连一些黑边,不影响答案。
题解链接
其实是把三道题强行拼在一起qwq

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cassert>
#define int long long
using namespace std;
const int N=105,M=10005,mod=1000000007;
int n,m,k,l,r,mid,tot,fa[N],pa[N],res[N],ans[N],tmp[N],id[N],num[N],x[N],y[N];
struct edge{
	int u,v,d,c;
}e[M];
bool cmp(edge a,edge b){
	return a.d==b.d?a.c<b.c:a.d<b.d;
}
int find(int u){
	return u==fa[u]?u:fa[u]=find(fa[u]);
}
int get(int u){
	return u==pa[u]?u:pa[u]=get(pa[u]);
}
bool check(){
	for(int i=1;i<=m;i++){
		if(!e[i].c){
			e[i].d+=mid;
		}
	}
	sort(e+1,e+m+1,cmp);
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	int cnt=0;
	for(int i=1,j=0;j<n-1;i++){
		int u=find(e[i].u),v=find(e[i].v);
		if(u!=v){
			fa[v]=u;
			j++;
			if(!e[i].c){
				cnt++;
			}
		}
	}
	for(int i=1;i<=m;i++){
		if(!e[i].c){
			e[i].d-=mid;
		}
	}
	return cnt>=k;
}
int fastpow(int a,int x){
	a%=mod;
	int res=1;
	while(x){
		if(x&1){
			res=res*a%mod;
		}
		x>>=1;
		a=a*a%mod;
	}
	return res;
}
int solve(int l,int r,int x){
	static int a[N][N];
	memset(a,0,sizeof(a));
	for(int i=l;i<=r;i++){
		int u=id[find(e[i].u)],v=id[find(e[i].v)];
		if(u==v){
			continue;
		}
		if(e[i].c){
			a[u][u]++;
			a[v][v]++;
			a[u][v]--;
			a[v][u]--;
		}else{
			a[u][u]+=x;
			a[v][v]+=x;
			a[u][v]-=x;
			a[v][u]-=x;
		}
	}
	memcpy(pa,fa,sizeof(fa));
	for(int i=2;i<=tot;i++){
		int u=get(num[i]),v=get(num[i-1]);
		if(u!=v){
			pa[v]=u;
			a[i][i]++;
			a[i-1][i-1]++;
			a[i][i-1]--;
			a[i-1][i]--;
		}
	}
	for(int i=1;i<=tot;i++){
		for(int j=1;j<=tot;j++){
			a[i][j]=(a[i][j]%mod+mod)%mod;
		}
	}
	int res=1;
	for(int i=1;i<tot;i++){
		for(int j=i+1;j<tot;j++){
			if(a[j][i]){
				int t=a[i][i]*fastpow(a[j][i],mod-2)%mod,tmp;
				for(int k=i;k<tot;k++){
					tmp=(a[i][k]-a[j][k]*t%mod+mod)%mod;
					a[i][k]=a[j][k];
					a[j][k]=tmp;
				}
				res=-res;
			}
		}
	}
	if(res==-1){
		res+=mod;
	}
	for(int i=1;i<tot;i++){
		res=res*a[i][i]%mod;
	}
	return res;
}
void lagerange(){
	static int a[N],b[N],c[N];
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c));
	memset(res,0,sizeof(res));
	a[0]=1;
	for(int i=0;i<=tot;i++){
		b[0]=0;
		for(int j=1;j<=i+1;j++){
			b[j]=a[j-1];
		}
		for(int j=0;j<=i;j++){
			b[j]=(b[j]-x[i]*a[j]%mod+mod)%mod;
		}
		for(int j=0;j<=i+1;j++){
			a[j]=b[j];
		}
	}
	for(int i=0;i<=tot;i++){
		for(int j=0;j<=tot+1;j++){
			b[j]=a[j];
		}
		for(int j=tot+1;j>=1;j--){
			c[j-1]=b[j];
			b[j-1]=(b[j-1]+1LL*b[j]*x[i]%mod)%mod;
		}
		int tmp=1;
		for(int j=0;j<=tot;j++){
			if(j!=i){
				tmp=tmp*(x[i]-x[j]+mod)%mod;
			}
		}
		tmp=y[i]*fastpow(tmp,mod-2)%mod;
		for(int j=0;j<=tot;j++){
			c[j]=c[j]*tmp%mod;
			res[j]=(res[j]+c[j])%mod;
		}
	}
}
signed main(){
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i=1;i<=m;i++){
		scanf("%lld%lld%lld%lld",&e[i].u,&e[i].v,&e[i].d,&e[i].c);
	}
	l=-1e9-1,r=1e9+1;
	while(l<r){
		mid=(l+r+1)/2;
		if(check()){
			l=mid;
		}else{
			r=mid-1;
		}
	}
	for(int i=1;i<=m;i++){
		if(!e[i].c){
			e[i].d+=l;
		}
	}
	sort(e+1,e+m+1,cmp);
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	ans[0]=1;
	for(l=1;l<=m;l=r+1){
		r=l;
		while(r<m&&e[r+1].d==e[l].d){
			r++;
		}
		memset(id,0,sizeof(id));
		tot=0;
		for(int i=l;i<=r;i++){
			int u=find(e[i].u),v=find(e[i].v);
			if(u!=v){
				if(!id[u]){
					id[u]=++tot;
					num[tot]=u;
				}
				if(!id[v]){
					id[v]=++tot;
					num[tot]=v;
				}
			}
		}
		if(!tot||tot==1){
			continue;
		}
		memcpy(pa,fa,sizeof(fa));
		for(int i=l;i<=r;i++){
			int u=find(e[i].u),v=find(e[i].v);
			if(u!=v){
				fa[v]=u;
			}
		}
		for(int i=0;i<=tot;i++){
			x[i]=i+1;
			y[i]=solve(l,r,i+1);
		}
		lagerange();
		memset(tmp,0,sizeof(tmp));
		for(int i=0;i<n;i++){
			for(int j=0;i+j<n;j++){
				tmp[i+j]+=ans[i]*res[j]%mod;
				tmp[i+j]%=mod;
			}
		}
		memcpy(ans,tmp,sizeof(tmp));
	}
	for(int i=2;i<=n;i++){
		if(find(i)!=find(1)){
			puts("0");
			return 0;
		}
	}
	printf("%lld\n",ans[k]);
	return 0;
}
根据提供的引用内容,你遇到的问题是在发送HTTP POST请求时收到了403 Forbidden的错误。这个错误通常表示你没有权限访问所请求的资源。 要解决这个问题,你可以采取以下步骤: 1. 首先,确保你的请求URL正确,并且你有权限访问该URL。你可以尝试在浏览器中直接访问该URL,看看是否能够成功访问。 2. 如果你确定URL是正确的,并且你有权限访问,那么可能是你的请求中缺少了必要的身份验证信息。你可以检查你的请求头中是否包含了正确的身份验证信息,比如Token或用户名密码。 3. 另外,你还可以检查服务器端的配置,确保你的请求被正确地处理和授权。你可以查看服务器的日志,以了解更多关于403错误的详细信息。 综上所述,当你收到403 Forbidden错误时,你应该首先检查URL和权限,然后确保请求中包含了正确的身份验证信息。如果问题仍然存在,你可以进一步检查服务器端的配置和日志,以找出问题的根本原因。 #### 引用[.reference_title] - *1* [kubeadm init报错10248...(The HTTP call equal to ‘curl -sSL http://localhost:10248/healthz‘ failed)](https://blog.youkuaiyun.com/weixin_45969972/article/details/123529966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [c/c++使用libcurl库做http客户端及封装(HTTP_GET和HTTP_POST)](https://blog.youkuaiyun.com/xsy29000/article/details/103181267)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值