# BZOJ 1016 JSOI 2008 最小生成树计数 Kruskal＋搜索

CODE：

#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 2010
#define MO 31011
using namespace std;

map<int,int> G;

struct Complex{
int x,y,len;

bool operator <(const Complex &a)const {
return len < a.len;
}
scanf("%d%d%d",&x,&y,&len);
}
}edge[MAX];

int points,edges;
int ones[MAX];

int father[MAX];
int ans = 1;

void Pretreatment()
{
for(int i = 1;i <= 1025; ++i)
ones[i] = ones[i >> 1] + (i&1);
}

int Find(int x)
{
if(!father[x] || father[x] == x)	return father[x] = x;
return father[x] = Find(father[x]);
}

bool Kruskal()
{
int cnt = 0;
for(int i = 1;i <= edges; ++i) {
int fx = Find(edge[i].x);
int fy = Find(edge[i].y);
if(fx != fy) {
father[fy] = fx;
G[edge[i].len]++;
cnt++;
}
}
if(cnt < points - 1)	return false;
return true;
}

void DFS(int pos)
{
if(pos > edges)	return ;
int st = pos,ed = pos,re = 0;
int cnt = G[edge[st].len];
if(!cnt) {
DFS(ed + 1);
return ;
}
while(edge[ed + 1].len == edge[st].len)	++ed;
for(int i = 0;i < (1 << (ed - st + 1)); ++i)
if(ones[i] == cnt) {
memset(father,0,sizeof(father));
int temp = i;
for(int j = st; temp; temp >>= 1,++j)
if(temp&1) {
int fx = Find(edge[j].x);
int fy = Find(edge[j].y);
if(fx == fy)	break;
father[fy] = fx;
}
if(!temp)	++re;
}
ans = (ans * re) % MO;
memset(father,0,sizeof(father));
for(int i = st; i <= ed; ++i) {
int fx = Find(edge[i].x);
int fy = Find(edge[i].y);
if(fx == fy)	continue;
father[fy] = fx;
}
for(int i = ed + 1;i <= edges; ++i)
edge[i].x = Find(edge[i].x),edge[i].y = Find(edge[i].y);
DFS(ed + 1);
}

int main()
{
Pretreatment();
cin >> points >> edges;
for(int i = 1;i <= edges; ++i)
sort(edge + 1,edge + edges + 1);
memset(father,0,sizeof(father));
if(!Kruskal()) {
cout << 0 << endl;
return 0;
}
DFS(1);
cout << ans << endl;
return 0;
}

posted @ 2017-05-05 12:49  yxysuanfa  阅读(116)  评论(0编辑  收藏