列表

详情


NC19855. K小生成树(kmst)

描述

给定一个n个点m条边的无向联通图G=(V,E),满足G中不存在自环。
你需要求G的一个生成树T,使得T的权值和在[L,R]内。
求满足条件的T的个数。

输入描述

第一行两个正整数n,m,表示点数和边数。
接下来m行,每行三个整数u,v,val,描述一条边。
接下来一行一个正整数q,表示询问的组数。
接下来q行,每行两个整数L,R,意义如“题目描述”

输出描述

对于每一组询问,输出一个非负整数表示答案。

示例1

输入:

3 5
1 2 1
1 3 2
1 3 7
2 3 4
2 3 3 
2
3 11
6 9

输出:

8
2

示例2

输入:

5 8
1 2 3
1 3 10
1 4 4
1 5 2
2 4 7
2 5 5
2 3 6
3 4 8
1
15 30

输出:

40

说明:

对于30%的数据,n<=8,L,R<=100
对于50%的数据,n<=10,m<=15
对于70%的数据,1<=L,R<=100000
对于另外10%的数据,val(u,v)两两相等,L=R。
对于100%的数据,1<=u,v<=n<=20,1<=m<=25,1<=q<=10000,1<=L<=R<=10^8,1<=val(u,v)<=10^7。
对于100%的数据,读入的所有L,R中,maxR-minL<=10^6。
请注意算法的常数优化。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 1112ms, 内存消耗: 736K, 提交时间: 2018-11-03 14:58:07

#include <cstdio>
#include <cstring>
#define F(i,x,y) for(int i=x;i<=y;++i)

using namespace std;

const int M=30;
int from[M],to[M],val[M],fa[M];
int n,m,q;
int A[10010],B[10010],ans[10010];

int G(int x){
	return fa[x]==x?x:G(fa[x]);
}

void dfs(int x,int s,int t){
	if(t==n-1){
		F(i,1,q){
			if(s>=A[i]&&s<=B[i]){
				ans[i]++;
			}
		}
		return ;
	}
	if(x==m+1) return ;
	
	dfs(x+1,s,t);
	int fx=G(from[x]),fy=G(to[x]);
	if(fx!=fy){
		fa[fx]=fy;
		dfs(x+1,s+val[x],t+1);
		fa[fx]=fx;
	}
}

int main(){
    scanf("%d%d",&n,&m);
    F(i,1,n) fa[i]=i;
    F(i,1,m){
    	scanf("%d%d%d",&from[i],&to[i],&val[i]);
	}
	
	scanf("%d",&q);
	F(i,1,q){
		scanf("%d%d",&A[i],&B[i]);
	}
	dfs(1,0,0);
	F(i,1,q) printf("%d\n",ans[i]);
    return 0;
}

上一题