构造一张二分图,左边是$n$个点,右边是$n-1$个集合,按照点属于集合连边

定义一组匹配的意义,即说明该点的父亲在该集合中选择

利用dinic求出二分图的最大匹配,若不为$n-1$则无解,否则考虑如何去构造一组解:

考虑左边剩下的未参与匹配的点$x$,将其作为根,并将所有含有$x$的集合所匹配的点都作为$x$的儿子,重复此过程(对于其他点,要加上一个“未被选择过”)

事实上,这个过程可以看作从源点出发在残余网络上的一棵bfs树,合法当且仅当能bfs到所有点

(能从$x$走到对应集合当且仅当其匹配的不是该集合,能从一个集合走到$y$当且仅当$y$匹配了该集合,同时$y$一定不会去选择其所匹配的集合中的点,因为一定被其父亲选择完毕)

下面,我们来证明若某一种匹配方式不能做到,则其余都不行:

由于根是任意的,换言之这个点作为根如果不行,其余点也都不行,因此确定了根

考虑调整匹配方案,一定可以通过若干次对一个序列的循环(通过将调整建为一张图可以证明)

若轮换前这一个集合中存在一个点能被搜到,按照轮换的顺序其余点都能被搜到,因此轮换前所有点都不能被搜到,即是一个内部的交换,没有意义

总复杂度为$o(n\sqrt{n})$,可以通过

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 #define oo 0x3f3f3f3f
5 struct ji{
6 int nex,to,len;
7 }edge[N<<3];
8 queue<int>q;
9 pair<int,int>ans[N];
10 int E,n,x,y,tot,head[N<<1],work[N<<1],d[N<<1];
11 void add(int x,int y,int z){
12 edge[E].nex=head[x];
13 edge[E].to=y;
14 edge[E].len=z;
15 head[x]=E++;
16 if (E&1)add(y,x,0);
17 }
18 bool bfs(){
19 memset(d,oo,sizeof(d));
20 d[0]=0;
21 q.push(0);
22 while (!q.empty()){
23 int k=q.front();
24 q.pop();
25 for(int i=head[k];i!=-1;i=edge[i].nex)
26 if ((edge[i].len)&&(d[edge[i].to]==oo)){
27 d[edge[i].to]=d[k]+1;
28 q.push(edge[i].to);
29 }
30 }
31 return d[2*n]<oo;
32 }
33 int dfs(int k,int s){
34 if (k==2*n)return s;
35 for(int &i=work[k];i!=-1;i=edge[i].nex)
36 if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
37 int p=dfs(edge[i].to,min(s,edge[i].len));
38 if (p){
39 edge[i].len-=p;
40 edge[i^1].len+=p;
41 return p;
42 }
43 }
44 return 0;
45 }
46 int dinic(){
47 int k,ans=0;
48 while (bfs()){
49 memcpy(work,head,sizeof(work));
50 while (k=dfs(0,oo))ans+=k;
51 }
52 return ans;
53 }
54 void bfs_build(){
55 memset(d,0,sizeof(d));
56 for(int i=head[0];i!=-1;i=edge[i].nex)
57 if (edge[i].len){
58 q.push(edge[i].to);
59 d[edge[i].to]=edge[i].to;
60 }
61 while (!q.empty()){
62 int k=q.front();
63 q.pop();
64 for(int i=head[k];i!=-1;i=edge[i].nex)
65 if ((edge[i].to)&&(edge[i].len)&&(!d[edge[i].to])){
66 if (edge[i].to>n)d[edge[i].to]=d[k];
67 else{
68 tot++;
69 ans[k-n]=make_pair(d[k],edge[i].to);
70 d[edge[i].to]=edge[i].to;
71 }
72 q.push(edge[i].to);
73 }
74 }
75 }
76 int main(){
77 scanf("%d",&n);
78 memset(head,-1,sizeof(head));
79 for(int i=1;i<=n;i++)add(0,i,1);
80 for(int i=1;i<n;i++){
81 scanf("%d",&x);
82 add(i+n,2*n,1);
83 for(int j=1;j<=x;j++){
84 scanf("%d",&y);
85 add(y,i+n,1);
86 }
87 }
88 if (dinic()<n-1){
89 printf("-1");
90 return 0;
91 }
92 bfs_build();
93 if (tot!=n-1)printf("-1");
94 else{
95 for(int i=1;i<n;i++)
96 printf("%d %d\n",ans[i].first,ans[i].second);
97 }
98 }

[atAGC029F]Construction of a tree的更多相关文章

  1. @atcoder - AGC029F@ Construction of a tree

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定 N - 1 个 {1, 2, ..., N} 的子集,第 ...

  2. AT4505-[AGC029F]Construction of a tree【构造题,hall定理,网络流】

    正题 题目链接:https://www.luogu.com.cn/problem/AT4505 题目大意 给出\(n\)个点和\(n-1\)个点集\(U_i\),每个点集中选择两个点连边使得该图是一棵 ...

  3. phylogeny analysis

    Multiple Alignment: MUSCLE ProbCons T-Coffee ClustalW Alignment curation: Gblocks Remove positions w ...

  4. 【AtCoder】AGC029(A-E)

    A - Irreversible operation 题解 把每个B后面的W个数累加起来即可 代码 #include <bits/stdc++.h> #define fi first #d ...

  5. JS进阶 - 浏览器工作原理

    一.浏览器的结构 浏览器的主要组件为: 用户界面 - 包括地址栏.前进/后退按钮.书签菜单等.除了浏览器主窗口(显示页面),其他部分都属于用户界面. 浏览器引擎 - 在用户界面和渲染引擎之间传送指令. ...

  6. Bounding Volume Hierarchy BVH in OpenCASCADE

    Bounding Volume Hierarchy BVH in OpenCASCADE eryar@163.com Abstract. Bounding Volume Hierarchy(BVH) ...

  7. WC2021 题目清单

    Day2 上午 <IOI题型与趣题分析> 来源 题目 完成情况 备注 IOI2002 Day1T1 Frog 已完成 IOI2002 Day1T2 Utopia IOI2002 Day1T ...

  8. 数据结构 - Codeforces Round #353 (Div. 2) D. Tree Construction

    Tree Construction Problem's Link ------------------------------------------------------------------- ...

  9. STL---Codeforces675D Tree Construction(二叉树节点的父亲节点)

    Description During the programming classes Vasya was assigned a difficult problem. However, he doesn ...

随机推荐

  1. redis分片集群安装部署

    redis分片集群安装与部署 分片集群的优势 高可用.且方便扩展. 数据分片,多节点提供服务,提高性能,数据提供冗余备份. 分片集群部署 只需更改配置文件 部署架构:6个节点,3主3从.数据集分为3片 ...

  2. 内网渗透DC-1靶场通关(CTF)

    最新博客见我的个人博客地址 DC系列共9个靶场,本次来试玩一下DC-1,共有5个flag,下载地址. 下载下来后是 .ova 格式,建议使用vitualbox进行搭建,vmware可能存在兼容性问题. ...

  3. [no code][scrum meeting] Beta 2

    例会时间:5月14日11:30,主持者:乔玺华 下次例会时间:5月15日11:30,主持者:肖思炀 一.工作汇报 人员 昨日完成任务 明日要完成的任务 乔玺华 - 开issue,分配时间 黎正宇 - ...

  4. DDL_Killer Alpha版本 Bug集中反馈处

    本博客用于DDL_Killer Alpha版本的Bug集中反馈. 您可以在本博客的下方评论区处留言,反馈您在使用DDl_Killer的过程中遇到的问题,以帮助我们更好的改进本产品. 我们会尽快修复找到 ...

  5. Noip模拟77 2021.10.15

    T1 最大或 $T1$因为没有开$1ll$右移给炸掉了,调了一年不知道为啥,最后实在不懂了 换成$pow$就过掉了,但是考场上这题耽误了太多时间,后面的题也就没办法好好打了.... 以后一定要注意右移 ...

  6. Noip模拟16 2021.7.15

    题目真是越来越变态了 T1 Star Way To Heaven 首先,你要看出这是一个最小生成树的题(妙吧?) 为什么可以呢? 我们发现从两点连线的中点过是最优的,但是上下边界怎么办呢? 我们把上下 ...

  7. 热身训练1 ping ping ping

    点此进入 题意: 一棵树,n+1 个节点,以0号节点为根,给出端点(a,b),节点a到节点b的路径上,至少有一个点是"坏掉的",求"坏掉的点"最少 分析: St ...

  8. 『学了就忘』Linux基础 — 5、使用VMware创建虚拟机

    目录 1.在VMware中创建虚拟机 (1)点击[创建新的虚拟机]. (2)选择系统安装方式 (3)选择客户机操作系统 (4)自定义虚拟机的名称和安装位置. (5)指定系统硬盘容量 (6)完成创建 2 ...

  9. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)

    一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...

  10. Ubuntu 16.04 curl 安装 使用

    curl是利用URL语法在命令行方式显工作的开元文件传输工具. 安装 $ sudo apt install -y curl 使用 $ curl http://www.baidu.com 这是最简单的使 ...