BZOJ 2582 : Bovine Alliance DFS
2582: [Usaco2012Jan]Bovine Alliance
Description
Input
* Line 1: Two space-separated integers N and M
* Lines 2..1+M: Line i+1 describes the ith trail. Each line contains two space-separated integers u_i and v_i (1 <= u_i, v_i <= N, u_i != v_i) describing the pair of farms connected by the trail. Note that there can be two trails between the same pair of farms.
Output
* Line 1: A single line containing the number of assignments of trails to farms, taken modulo 1,000,000,007. If no assignment satisfies the above conditions output 0.
Sample Input
1 2
3 2
4 5
4 5
Sample Output
思路 :
本题理清思路考虑就好了,因为集合只存在两种情况 即 只有一个点,或者 一个点配一个边, 那么只需要对每个联通块分情况考虑 。若V<E 那么肯定有边不在集合里,直接输出0
若V==E,则只要确定该联通块和哪个点分组,整个联通块的分组情况就确定了,而一条边只会有两种分组情况,故对答案的贡献为2, 如果V==E+1 则联通块是个树,那么任选一个点为根,都有一种方案,故对答案的贡献为V。
而具体维护的方法我们可以采用并查集(Tarjan肯定也是可以的,但我没有写)来维护一下联通块的信息,最后把每个联通块的ANS乘到一起就是答案,别忘了mod1e9+7哦!
下面附上代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int p = 1e9+7;
int fa[110000],psiz[110000],esiz[110000];
long long ans;
struct node {
int s,t;
}e[110000];
int find(int x) {
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main() {
int n, m, s, t;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
fa[i]=i,psiz[i]=1;
for(int i=1;i<=m;i++) {
scanf("%d%d",&s,&t);
int dx=find(s),dy=find(t);
if(dx!=dy)
fa[dx]=dy,
esiz[dy]+=esiz[dx]+1,
psiz[dy]+=psiz[dx];
else esiz[dx]++;
}
ans=1;
for(int i=1;i<=n;i++)
if(fa[i]==i)
if(psiz[i]==esiz[i]+1)
(ans*=psiz[i])%=p;
else if(psiz[i]==esiz[i])
(ans*=2)%=p;
else {
puts("0");
return 0;
}
printf("%lld\n",ans%p);
}
欢迎来原Blog看看 >原文链接<

浙公网安备 33010602011771号