【CF MEMSQL 3.0 E. Desk Disorder】
time limit per test 2 seconds
memory limit per test 256 megabytes
input standard input
output standard output
A new set of desks just arrived, and it's about time! Things were getting quite cramped in the office. You've been put in charge of creating a new seating chart for the engineers. The desks are numbered, and you sent out a survey to the engineering team asking each engineer the number of the desk they currently sit at, and the number of the desk they would like to sit at (which may be the same as their current desk). Each engineer must either remain where they sit, or move to the desired seat they indicated in the survey. No two engineers currently sit at the same desk, nor may any two engineers sit at the same desk in the new seating arrangement.
How many seating arrangements can you create that meet the specified requirements? The answer may be very large, so compute it modulo 1000000007 = 109 + 7.
Input
Input will begin with a line containing N (1 ≤ N ≤ 100000), the number of engineers.
N lines follow, each containing exactly two integers. The i-th line contains the number of the current desk of the i-th engineer and the number of the desk the i-th engineer wants to move to. Desks are numbered from 1 to 2·N. It is guaranteed that no two engineers sit at the same desk.
Output
Print the number of possible assignments, modulo 1000000007 = 109 + 7.
Examples
input
4
1 5
5 2
3 7
7 3
output
6
input
5
1 10
2 10
3 10
4 10
5 5
output
5
Note
These are the possible assignments for the first example:
- 1 5 3 7
- 1 2 3 7
- 5 2 3 7
- 1 5 7 3
- 1 2 7 3
- 5 2 7 3
【翻译】有2*n个座位,输入每一个人的原位和理想位置,现在需要为每一个人分配一个独一无二的位置使得每个人坐在理想位置或者原位置上。输出方案数(%1000000007)。
题解:
①使用建图分来讨论来转化问题。
②使用有向边从原位指向理想位置:
仅有如下三种情况:
(1)一个自环或者一堆链状结构最终止于一个自环
(2)一根或者一堆链状结构最终止于一个不与其他点和自身成环的点
(3)形成环(非自环)
那么对于(1),ans*=1(只用一种),对于(2)ans*=节点数(任意一个点可以移动一次),
对于(3)ans*=2(仅有两种情况——都在原位或者都在理想位置)
#include<stdio.h> #define M 1000000007 #define go(i,a,b) for(int i=a;i<=b;i++) const int N=200004; long long ans=1;int n,fa[N],Type[N],siz[N],u,v,U,V; int find(int x){return fa[x]=x==fa[x]?x:find(fa[x]);} int main() { scanf("%d",&n);n<<=1; go(i,1,n)fa[i]=i,siz[i]=1; go(i,1,n/2) { scanf("%d%d",&u,&v); U=find(u),V=find(v); if(u==v){Type[U]=1;continue;} if(U==V){Type[U]=2;continue;} Type[U]|=Type[V];siz[fa[V]=U]+=siz[V]; } go(i,1,n)if(i==find(i))ans=ans*(Type[i]?Type[i]:siz[i])%M; printf("%d\n",(ans%M+M)%M);return 0; }//Paul_Guderian