[USACO12JAN]牛联盟Bovine Alliance
传送门:https://www.luogu.org/problemnew/show/P3043
其实这道题十分简单。。看到大佬们在用tarjan缩点,并查集合并。。。。
蒟蒻渣渣禹都不会。
渣渣禹发现,给出的图经过处理之后会出现:
环。
不是环。
不是环的情况我们有n中匹配方式(n为其点的个数)
是环的情况我们只有两种匹配方式,顺时针匹配和逆时针匹配。
所以我们dfs处理出图中有多少个环,和不是环的个数。
ans 初始为1.
遇到环ans乘二,否则ans乘n(n为这个不是环的点的个数)。
结束咯w。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | #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; } |