考虑一个构造,对于坐标$(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. 【UE4】GAMES101 图形学作业1:mvp 模型、视图、投影变换

    总览 到目前为止,我们已经学习了如何使用矩阵变换来排列二维或三维空间中的对象.所以现在是时候通过实现一些简单的变换矩阵来获得一些实际经验了.在接下来的三次作业中,我们将要求你去模拟一个基于CPU 的光 ...

  2. Beta实际开发与初始计划的比较

    零.说明 本篇博客为Beta阶段开始十天后,实际开发工作与初始计划的比较 截止至本篇博客发布为止,团队所有成员已完成计网考试,将在本周日进行充分的接口测试 一.比较 1.与初始计划对比 初始计划 实际 ...

  3. 乘风破浪,遇见上一代操作系统Windows 10 - 抢鲜尝试安装新微软商店(Microsoft Store)

    背景 在微软官方文章的<十一项关于微软商店新知>中提到: 新的微软商店现在可在Windows 11上找到,我们很高兴地分享,它将在未来几个月内提供给Windows 10客户!我们将很快分享 ...

  4. 解决svn异常报错“”cleanup failed to process the following paths …… previous operation has not finished”

    参考高票答案https://stackoverflow.com/questions/10128201/subversion-stuck-due-to-previous-operation-has-no ...

  5. 嵌入式单片机之stm32串口你懂了多少!!

    stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...

  6. TCP 拥塞窗口原理

    学过网络相关课程的,都知道TCP中,有两个窗口: 滑动窗口(在我们的上一篇文章中有讲),接收方通过通告发送方自己的可以接受缓冲区大小(这个字段越大说明网络吞吐量越高),从而控制发送方的发送速度. 拥塞 ...

  7. 2021 CCPC女生赛

    newbie,A了五题铜牌收工 比赛时和队友悠哉游哉做题,想着干饭,最后幸好没滚出铜尾. 贴一下比赛过的代码 A题 签到 队友A的,判断正反方向序列是否符合要求 /*** * @Author: _Kr ...

  8. 树的子结构 牛客网 剑指Offer

    树的子结构 牛客网 剑指Offer 题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) # class TreeNode: # def __init_ ...

  9. 『学了就忘』Linux基础命令 — 18、Linux命令的基本格式

    目录 1.命令提示符说明 2.命令的基本格式 (1)举例ls命令 (2)说明ls -l命令的 输出内容 1.命令提示符说明 [root@localhost ~] # []:这是提示符的分隔符号,没有特 ...

  10. Android现有工程使用Compose

    Android现有工程使用Compose 看了Compose的示例工程后,我们也想使用Compose.基于目前情况,在现有工程基础上添加Compose功能. 引入Compose 首先我们安装 Andr ...