题解 P3043 [USACO12JAN]牛联盟Bovine Alliance

Posted nhdr233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 P3043 [USACO12JAN]牛联盟Bovine Alliance相关的知识,希望对你有一定的参考价值。

题意:现在有$n$个点,$m$条边的图,$1 \leq m \leq n$,让点和其所连边进行配对,一个点或边只能配对一次,所有边必须配对,而点可以无需配对

这题有思维无码量还是比较友好的

现在我们有一张连通图,设它边数为$m$,点数为$n$,显然$m \ge n-1$

根据题意,一个点只能和一条边配对,自然的若在当前图中$m > n$,则是无解的

接下来进行分类讨论

$m=n$的情况下,有点类似**基环树**的感觉...思考和环有关的性质,若现在有一条环,每个点要和一条边进行匹配,不难发现匹配方案只有**两种**,因为一个点只和两条边相连嘛...对于基环上任意一个点的子树,因为**根节点必须与一条环上边匹配,所以其子树上任意一个节点只有子节点匹配其连向父节点的边一个选择**

$m=n-1$的情况下,借用上面的结论,每个子节点首先应该与其连向父节点的边匹配,而当前情况下我们**允许且只允许一个点不进行匹配**,那么方案数显然就是$n$了,可以画图理解

至于统计边数,就有很多种写法了,可以按照自己的思路写

//2019/8/7->Riko->AtNCU->luoguP3043
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>

namespace Rikopack 
    bool digit (int ch)  return (ch <= ‘9‘ and ch >= ‘0‘);
    inline int in () 
    	int x = 0, ch = getchar(), base = 1;
    	while (!digit(ch)) 
    	    if (ch == ‘-‘) base = -1;
    	    ch = getchar();
    	
    	while (digit(ch)) x = x*10+ch-‘0‘, ch = getchar();
    	return x*base;
    
    template <typename T> inline void smax (T& x, T y)  if (x < y) x = y;
    template <typename T> inline void smin (T& x, T y)  if (x > y) x = y;
    void print (int x)  printf("debug:%d\n", x);
    const int MAXINT = 2123456789;
    #define LL long long
    //Believing heart is your power

using namespace Rikopack;
using namespace std;

const int N = 101000, mod = 1e9+7;
int n, m, tmp, ans, Size, Edges;
int vis[N];
int nxt[N<<1], to[N<<1], bol[N], head[N], edgeind;
inline void add (int u, int v) 
	int i = ++edgeind;
	nxt[i] = head[u]; to[i] = v; head[u] = i;


void Getcir (int x, int fa) 
	vis[x] = true; Size++;
	for (int i = head[x]; i; i = nxt[i]) 
		int e = to[i];
		if (!bol[(i+1)/2]) 
			bol[(i+1)/2] = true;
			++Edges;
		
		if (e == fa or vis[e]) continue;
		Getcir(e, x);
	

void work (int x) 
	Edges = Size = tmp = 0;
	Getcir(x, 0);
	if (Edges == Size) tmp = 2;
	if (Edges == Size-1) tmp = Size;

void prepare () 
	n = in(); m = in();
	for (int i = 1; i <= m; ++i) 
		int u = in(), v = in();
		add(u, v); add(v, u);
	
	ans = 1;
	for (int i = 1; i <= n; ++i) 
		if (!vis[i]) work(i);
		else continue;
		ans = ((LL)ans*tmp)%mod; 
		if (!ans) 
			puts("0"); return;
		
	
	printf("%d", ans);

int main ()  prepare();

  

以上是关于题解 P3043 [USACO12JAN]牛联盟Bovine Alliance的主要内容,如果未能解决你的问题,请参考以下文章

P3043 [USACO12JAN]牛联盟Bovine Alliance(并查集)

[USACO12JAN]牛联盟Bovine Alliance

bzoj1635[Usaco2007 Jan]Tallest Cow 最高的牛*

题解 P2419 [USACO08JAN]牛大赛Cow Contest

P2419 [USACO08JAN]牛大赛Cow Contest

P2879 [USACO07JAN]区间统计Tallest Cow {前缀和,思维}