考虑一个构造,对于坐标$(x,y)$,连一条$x$到$y$的边(注意:横坐标和纵坐标即使权值相同也是不同的点),之后每一个连通块独立,考虑一个连通块内部:

每一个点意味着一次删除操作,每一个边意味着一个坐标,由于每一次操作最多删除一个点,因此首先点数要大于等于边数,同时总边数=总点数=$2n$,因此每一个连通块都是基环树

考虑叶子,其必然要删除一个点,只能是与其相连的边,重复此过程,对于不在环上的点或边都可以确定删除的配对关系,对于环上的点枚举两种方向也可以确定

接下来,就是要对于一组给定的配对关系,求对应的方案数,然后相加即为该连通块的方案数

再建一张新图,点仍然是操作,边是有向边,表示操作的先后顺序,考虑如何建图:

1.如果操作$x_{1}$消除了$(x,y)$,那么所有$(x,y')$(其中$y'<y$)都应在其之前被删除,即删除这些点的操作要在$(x,y)$之前,更具体的,将与$x$相连且比$y$小的点向$x$连边

2.同时,我们要保证$(x,y)$不被$y_{2}$删除,但这个的充分条件为$y_{2}$删除了$(x',y)$,而根据上述的边也满足了此条件,因此不必考虑

对于新图,统计方案数:如果存在环,那么方案数为0,否则必然是一棵内向树森林(因为每一个点至多向其父亲连边),考虑dp

令$f_{i}$表示以$i$为根的子树的方案数,由于根必须是子树中最早删除的节点,令$sz_{i}$表示$i$子树大小,$V$表示总点数,则有$ans=\frac{V!}{\prod sz_{i}}$

(可以这么看待这个式子:对于所有排列中,对于$i$其在子树内删除的名次是随机的,而只有是子树中第一个被删除才符合条件,因此是$\frac{1}{sz_{i}}$种)

假设一个连通块点数为$V_{i}$,方案数为$S_{i}$,不难得到$ans=\frac{(2n)!}{\prod V_{i}!}\prod S_{i}$,计算即可

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 #define mod 1000000007
5 struct ji{
6 int nex,to;
7 }edge[N<<1];
8 vector<int>v,g[N];
9 int E,n,x,y,tot,ans,head[N],vis[N],f[N],p[N],r[N],sz[N],fac[N],inv[N];
10 void add(int x,int y){
11 edge[E].nex=head[x];
12 edge[E].to=y;
13 head[x]=E++;
14 }
15 void dfs(int k,int fa){
16 f[k]=p[k]=fa;
17 vis[k]=1;
18 v.push_back(k);
19 for(int i=head[k];i!=-1;i=edge[i].nex)
20 if (edge[i].to!=fa){
21 if (!vis[edge[i].to])dfs(edge[i].to,k);
22 else{
23 tot++;
24 if (!x)x=edge[i].to;
25 else y=edge[i].to;
26 }
27 }
28 }
29 void dfs(int k){
30 if (sz[k])return;
31 sz[k]=1;
32 for(int i=0;i<g[k].size();i++){
33 dfs(g[k][i]);
34 sz[k]+=sz[g[k][i]];
35 }
36 }
37 int calc(){
38 for(int i=0;i<v.size();i++){
39 sz[v[i]]=0;
40 g[v[i]].clear();
41 }
42 for(int i=0;i<v.size();i++)
43 if (p[p[v[i]]]>v[i])g[p[v[i]]].push_back(v[i]);
44 for(int i=0;i<v.size();i++)dfs(v[i]);
45 int ans=1;
46 for(int i=0;i<v.size();i++)ans=1LL*ans*inv[sz[v[i]]]%mod;
47 return ans;
48 }
49 int main(){
50 fac[0]=inv[0]=inv[1]=1;
51 for(int i=1;i<N-4;i++)fac[i]=1LL*fac[i-1]*i%mod;
52 for(int i=2;i<N-4;i++)inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
53 scanf("%d",&n);
54 memset(head,-1,sizeof(head));
55 for(int i=1;i<=2*n;i++){
56 scanf("%d%d",&x,&y);
57 add(x,y+n);
58 add(y+n,x);
59 }
60 ans=fac[2*n];
61 for(int i=1;i<=2*n;i++)
62 if (!vis[i]){
63 v.clear();
64 x=y=tot=0;
65 dfs(i,0);
66 if (tot>2){
67 printf("0");
68 return 0;
69 }
70 for(int j=y;j!=i;j=f[j])p[f[j]]=j;
71 p[y]=x;
72 int s=calc();
73 for(int j=y;j!=x;j=f[j])p[j]=f[j];
74 p[x]=y;
75 ans=1LL*ans*(s+calc())%mod;
76 }
77 printf("%d",ans);
78 }

[atARC083F]Collecting Balls的更多相关文章

  1. Arc083_F Collecting Balls

    传送门 题目大意 给定$N$,在$(1,0),(2,0)......(N,0)$和$(0,1),(0,2)...(0,N)$上都有$1$个机器人,同时给定$2N$个坐标$(x,y),x,y\in[1, ...

  2. [ARC083F] Collecting Balls [建二分图+环套树定向+建拓扑图+树的拓扑序计数]

    题面 [传送门](https://arc083.contest.atcoder.jp/tasks/arc083_d) 思路 这是一道真正的好题 第一步:转化模型 行列支配类的问题,常见做法就是把行和列 ...

  3. 【AtCoder Beginner Contest 074 B】Collecting Balls (Easy Version)

    [链接]h在这里写链接 [题意] 看懂题目之后就会发现是道大水题. [题解] 在这里写题解 [错的次数] 0 [反思] 在这了写反思 [代码] #include <bits/stdc++.h&g ...

  4. 题解-AtCoder ARC-083F Collecting Balls

    Problem ARC083F 题意概要:给定 \(2n\) 个二维平面上的球,坐标分别为 \((x_i,y_i)\),并给出 \(n\) 个 \(A\)类 机器人 和 \(n\) 个 \(B\)类 ...

  5. [ARC083]Collecting Balls

    Description 有一个 \(n\times n\) 的矩阵,矩阵内有 \(2n\) 个球.对于 \(i \in [1,n]\) ,\((0,i) (i,0)\) 的位置各有一个启动后往右走/往 ...

  6. Atcoder 乱做

    最近感觉自己思维僵化,啥都不会做了-- ARC103 F Distance Sums 题意 给定第 \(i\) 个点到所有点的距离和 \(D_i\) ,要求构造一棵合法的树.满足第 \(i\) 个点到 ...

  7. 【AtCoder】ARC083

    C - Sugar Water 计算一下可以达到水是多少,可以到达的糖是多少 枚举水,然后加最多能加的糖,是\(min(F - i *100,E * 100)\),计算密度,和前一个比较就行 #inc ...

  8. AtCoder刷题记录

    构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...

  9. POJ2096 Collecting Bugs

    Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 5090   Accepted: 2529 Case Time Limit: ...

随机推荐

  1. Markdown语法熟悉

    ==(1)标题== # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标题 ==(2)字体== **加粗** *斜体* ***斜体加粗*** ...

  2. NOI2018屠龙勇士(扩展CRT + splay(multiset))

    QWQ 一到假期就颓废 哎 今年新鲜出炉的NOI题,QwQ同步赛的时候写的,后来交了一发洛谷,竟然过了 首先 根据题目,我们很容易得到,假设对应每一条龙的剑的攻击力是\(atk\)的话 \[a_i-x ...

  3. Spring 框架学习

    转载自前辈:我没有三个新脏 Spring学习(1)--快速入门 认识 Spring 框架 Spring 框架是 Java 应用最广的框架,它的成功来源于理念,而不是技术本身,它的理念包括 IoC (I ...

  4. Tomcat实现自定义类加载器

    什么是类加载器? 这是官方给的定义 在 Java 虚拟机的实现中,初始类可以作为命令行参数提供. 或者,该实现可以提供一个初始类,该类设置一个类加载器,该类加载器依次加载应用程序. 初始类的其他选择也 ...

  5. HCNP Routing&Switching之BGP邻居建立条件、优化和认证

    前文我们了解了BGP相关概念.AS相关概念以及BGP邻居类型.基础配置等,相关回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15370838.html:今天我们 ...

  6. filebeat收集日志到elsticsearch中并使用ingest node的pipeline处理

    filebeat收集日志到elsticsearch中 一.需求 二.实现 1.filebeat.yml 配置文件的编写 2.创建自定义的索引模板 3.加密连接到es用户的密码 1.创建keystore ...

  7. Java High Level REST Client 使用地理位置查询

    Java High Level REST Client 使用地理位置查询 一.需求 二.对应的query语句 三.对应java代码 1.引入 jar 包 2.创建 RestHighLevelClien ...

  8. Golang通脉之并发初探

    并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发. 并发与并行 并发:同一时间段内执行多个任务. 并行:同一时刻执行多个任务,有时间上的重叠. 进程.线程.协程 进程(Process) ...

  9. 一个C#开发搭建Android框架的心路历程

    前言 Java框架实在是太多了,因为是初学乍练,所以,只好以百度为标准选择框架了. Java的框架文章太难写了,因为他引用了太多框架,而没一个框架都有很繁琐的配置,把每个框架都写一遍,就等于写书了:所 ...

  10. Python super(Todo,self).__init__() TypeError: super() argument 1 must be type, not classobj

    示例如下 class A(): def __init__(self):pass class B(A): def __init__(self): super(A, self).__init__() 当调 ...