[USACO12JAN]牛联盟Bovine Alliance

传送门https://www.luogu.org/problemnew/show/P3043

其实这道题十分简单。。看到大佬们在用tarjan缩点,并查集合并。。。。

蒟蒻渣渣禹都不会。

渣渣禹发现,给出的图经过处理之后会出现:

环。

不是环。

不是环的情况我们有n中匹配方式(n为其点的个数)
是环的情况我们只有两种匹配方式,顺时针匹配和逆时针匹配。 所以我们dfs处理出图中有多少个环,和不是环的个数。 ans 初始为1. 遇到环ans乘二,否则ans乘n(n为这个不是环的点的个数)。 结束咯w。
#define B cout << "BreakPoint" << endl;
#define O(x) cout << #x << " " << x << endl;
#define O_(x) cout << #x << " " << x << " ";
#define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#define LL long long
#define N 100005
#define p 1000000007
using namespace std;
inline int read() {
	int s = 0,w = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-')
			w = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9') {
		s = s * 10 + ch - '0';
		ch = getchar();
	}
	return s * w;
}
int to[2 * N],nxt[2 * N],head[2 * N],vis[N],tot;
int tmp,res;
LL ans = 1;
void add(int u,int vis) {
	to[++tot] = vis;
	nxt[tot] = head[u];
	head[u] = tot;
	return ;
}
void dfs(int x) {
	vis[x] = 1;
	tmp++;
	for(int i = head[x]; i; i = nxt[i],res++)
		if(!vis[to[i]])
			dfs(to[i]);
}
int n,m;
void init() {
	n = read(),m = read();
	for(int i = 1; i <= m; i++) {
		int x = read(),y = read();
		add(x,y);
		add(y,x);
	}
}
void solve() {
	for(int i = 1; i <= n; i++) {
		if(!vis[i]) {
			tmp = res = 0;
			dfs(i);
			if(tmp > res / 2) 
				ans = ans * tmp % p;
			else 
				if(tmp == res / 2) 
					ans = ans * 2 % p;
			else ans = 0;
		}
	}
	printf("%lld",ans);
}
int main(){
	init();
	solve();
	return 0;
}

  

 
原文地址:https://www.cnblogs.com/excellent-zzy/p/10786285.html