1016: [JSOI2008]最小生成树计数
2017-02-22 20:24
513 查看
传送门
并查集好题。
用暴力求出最小生成树,确定每一种长度的边在图中的数量。
又Kruscal算法流程知,每一种长度的边在图中的数量一定(否则存在更优解)
对于每一个长度的边,爆搜求出方案个数。
运用乘法原理求解即可。
P.S:本题并查集无需路径压缩。/**************************************************************
Problem: 1016
User: zhouyuyang
Language: C++
Result: Accepted
Time:8 ms
Memory:2620 kb
****************************************************************/
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
struct orzhhd{
int x,y,z;
}a[10005],e[100005];
int n,m,u,v,ans,sum,cnt,tot;
int fa[10005];
bool cmp(orzhhd a,orzhhd b){
return a.z<b.z;
}
int getf(int x){
return fa[x]==x?x:getf(fa[x]);
}
void dfs(int x,int now,int k){
if (now==e[x].y+1){
if (k==e[x].z) sum++;
return;
}
int u=getf(a[now].x);
int v=getf(a[now].y);
if (u!=v){
fa[u]=v;
dfs(x,now+1,k+1);
fa[u]=u;
fa[v]=v;
}
dfs(x,now+1,k);
return;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
sort(a+1,a+m+1,cmp);
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=m;i++){
u=getf(a[i].x);
v=getf(a[i].y);
if (a[i].z!=a[i-1].z){
e[cnt].y=i-1;
cnt++;
e[cnt].x=i;
}
if (u!=v){
fa[u]=v;
e[cnt].z++;
tot++;
}
}
e[cnt].y=m;
for (int i=1;i<=n;i++) fa[i]=i;
if (tot!=n-1){
printf("0");
return 0;
}
ans=1;
for (int i=1;i<=cnt;i++){
sum=0;
dfs(i,e[i].x,0);
ans=(ans*sum)%31011;
for (int j=e[i].x;j<=e[i].y;j++){
u=getf(a[j].x);
v=getf(a[j].y);
if (u!=v) fa[u]=v;
}
}
printf("%d",ans);
}
并查集好题。
用暴力求出最小生成树,确定每一种长度的边在图中的数量。
又Kruscal算法流程知,每一种长度的边在图中的数量一定(否则存在更优解)
对于每一个长度的边,爆搜求出方案个数。
运用乘法原理求解即可。
P.S:本题并查集无需路径压缩。/**************************************************************
Problem: 1016
User: zhouyuyang
Language: C++
Result: Accepted
Time:8 ms
Memory:2620 kb
****************************************************************/
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
struct orzhhd{
int x,y,z;
}a[10005],e[100005];
int n,m,u,v,ans,sum,cnt,tot;
int fa[10005];
bool cmp(orzhhd a,orzhhd b){
return a.z<b.z;
}
int getf(int x){
return fa[x]==x?x:getf(fa[x]);
}
void dfs(int x,int now,int k){
if (now==e[x].y+1){
if (k==e[x].z) sum++;
return;
}
int u=getf(a[now].x);
int v=getf(a[now].y);
if (u!=v){
fa[u]=v;
dfs(x,now+1,k+1);
fa[u]=u;
fa[v]=v;
}
dfs(x,now+1,k);
return;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
sort(a+1,a+m+1,cmp);
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=m;i++){
u=getf(a[i].x);
v=getf(a[i].y);
if (a[i].z!=a[i-1].z){
e[cnt].y=i-1;
cnt++;
e[cnt].x=i;
}
if (u!=v){
fa[u]=v;
e[cnt].z++;
tot++;
}
}
e[cnt].y=m;
for (int i=1;i<=n;i++) fa[i]=i;
if (tot!=n-1){
printf("0");
return 0;
}
ans=1;
for (int i=1;i<=cnt;i++){
sum=0;
dfs(i,e[i].x,0);
ans=(ans*sum)%31011;
for (int j=e[i].x;j<=e[i].y;j++){
u=getf(a[j].x);
v=getf(a[j].y);
if (u!=v) fa[u]=v;
}
}
printf("%d",ans);
}
相关文章推荐
- 【JSOI 2008】【BZOJ 1016】最小生成数计数
- 【BZOJ1016】[JSOI2008]最小生成树计数
- BZOJ1016 JSOI2008 最小生成树计数
- BZOJ 1016 【JSOI2008】 最小生成树计数
- 1016: [JSOI2008]最小生成树计数 - BZOJ
- bzoj1016:[JSOI2008]最小生成树计数
- bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)
- [bzoj1016][JSOI2008]最小生成树计数【MST】【暴力】
- BZOJ1016 && JSOI2008] 最小生成树计数
- [BZOJ1016][JSOI2008]最小生成树计数(结论题)
- 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)
- BZOJ1016 && JSOI2008] 最小生成树计数
- 【Kruskal+dfs】BZOJ1016- [JSOI2008]最小生成树计数
- 【bzoj1016】[JSOI2008]最小生成树计数
- bzoj 1016: [JSOI2008]最小生成树计数
- [BZOJ]1016 JSOI2008 最小生成树计数
- 【BZOJ1016】[JSOI2008]最小生成树计数【最小生成树】【搜索】
- bzoj1016 [JSOI2008]最小生成树计数
- BZOJ 1016 JSOI 2008 巨额奖金 最小生成树计数
- BZOJ1016 [JSOI2008]最小生成树计数