有趣啊~手玩一下这棵树,发现因为连边只对相连点的位数有限制,我们可以认为是在往一棵已经有 m 个结点的树上挂叶子结点直到满足要求。(m = log(10) n)。注意由于 m 超级无敌小,我们可以直接爆搜初始树,然后 dinic 二分图匹配即可。(网络流:一边的点表示限制,另一边的点表示位数。每一条限制可以删去一个节点, 检验一下是否能够删完即可)。

#include <bits/stdc++.h>
using namespace std;
#define maxn 300000
#define INF 9999999
int n, m, cal[maxn], num[maxn], cur[maxn];
int tot, mark[7][7], rec[7][7], lev[maxn];
int S, T, Q[maxn], d[maxn], deg[maxn];
char s1[maxn], s2[maxn];
priority_queue <int, vector <int>, greater <int> > q;int read()
{int x = 0, k = 1;char c; c = getchar();while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();return x * k;
}struct edge
{int cnp, to[maxn], last[maxn], head[maxn], f[maxn], F[maxn];edge() { cnp = 2; }void add(int u, int v, int fl){//    cout << "*****" << u << " " << v << " " << fl << endl;to[cnp] = v, f[cnp] = F[cnp] = fl, last[cnp] = head[u], head[u] = cnp ++;to[cnp] = u, f[cnp] = F[cnp] = 0, last[cnp] = head[v], head[v] = cnp ++;}
}E1;struct node
{int u, v;
}id[maxn];bool bfs()
{queue <int> q; memset(lev, 0, sizeof(lev)); lev[S] = 1; q.push(S);while(!q.empty()){int u = q.front(); q.pop();for(int i = E1.head[u]; i; i = E1.last[i]){int v = E1.to[i];if(E1.f[i] && !lev[v]){lev[v] = lev[u] + 1;q.push(v);}}if(lev[T]) return 1;}return 0;
}int dfs(int u, int nf)
{if(u == T || !nf) return nf;int tf = 0;for(int i = E1.head[u]; i; i = E1.last[i]){int v = E1.to[i]; if(!E1.f[i] || lev[v] != lev[u] + 1) continue;int af = dfs(v, min(E1.f[i], nf));tf += af, nf -= af;E1.f[i] -= af, E1.f[i ^ 1] += af;}return tf;
}int dinic()
{int nf = 0;while(bfs()) nf += dfs(S, INF);return nf;
}void dfs2(int u)
{for(int i = E1.head[u]; i; i = E1.last[i]){int v = E1.to[i]; if(!E1.f[i ^ 1]) continue;if(u > m && u <= tot + m && v >= 1 && v <= m) for(int j = 1; j <= E1.f[i ^ 1]; j ++){int t = u - m; t = (id[t].u == v) ? id[t].v : id[t].u;printf("%d %d\n", num[t], cur[v] ++);}if(u == S) dfs2(v);}
}void Search(int now)
{if(now >= m - 1){int t = 1;for(int i = 1; i <= m; i ++) d[i] = deg[i];for(int i = 1; i <= m; i ++) if(!d[i]) q.push(i);memset(mark, 0, sizeof(mark));while(!q.empty() && t <= m - 2){int u = q.top(); q.pop();int x = u, y = Q[t]; if(x > y) swap(x, y);mark[x][y] = 1; d[Q[t]] --;if(!d[Q[t]]) q.push(Q[t]); t ++;}if(q.size() >= 2){int x = q.top(); q.pop(); int y = q.top(); q.pop();mark[x][y] = 1;}else if(q.size() >= 1) q.pop();for(int i = 2; i < E1.cnp; i ++) E1.f[i] = E1.F[i];for(int i = E1.head[S]; i; i = E1.last[i]){int v = E1.to[i]; if(!v) continue; v -= m;int x = id[v].u, y = id[v].v;if(x > y) swap(x, y);E1.f[i] -= mark[x][y]; if(E1.f[i] < 0) return;}if(dinic() == n - m) {for(int i = 1; i <= m; i ++)for(int j = i + 1; j <= m; j ++)if(mark[i][j]) printf("%d %d\n", num[i], num[j]);for(int i = 1; i <= m; i ++) cur[i] ++;dfs2(S);exit(0);}return;}for(int i = 1; i <= m; i ++) deg[i] ++, Q[now] = i, Search(now + 1), deg[i] --;
}int main()
{n = read(); int t = n;while(t) { m ++; t /= 10; }for(int i = 1, l = 1; i <= m; l *= 10, i ++) num[i] = cur[i] = l;for(int i = 1, l = 1; i < m; l *= 10, i ++) cal[i] = l * 10 - num[i]; cal[m] = n - num[m] + 1; S = 0, T = m * m + m + 3;for(int i = 1; i < n; i ++){scanf("%s%s", s1 + 1, s2 + 1);int l1 = strlen(s1 + 1), l2 = strlen(s2 + 1);if(l1 > l2) swap(l1, l2); rec[l1][l2] ++;}for(int i = 1; i <= m; i ++)for(int j = i; j <= m; j ++){id[++ tot].u = i, id[tot].v = j;E1.add(S, tot + m, rec[i][j]);E1.add(tot + m, i, INF); E1.add(tot + m, j, INF);}for(int i = 1; i <= m; i ++) E1.add(i, T, cal[i] - 1);Search(1);printf("-1\n");return 0;
}

转载于:https://www.cnblogs.com/twilight-sx/p/9960810.html

【题解】CF#611 H-New Year and Forgotten Tree相关推荐

  1. 【VK Cup 2016 - Round 1 (Div 2 Edition)C】【构造】Bear and Forgotten Tree 3 构造一棵树直径为d且点1的深度为h

    Bear and Forgotten Tree 3 time limit per test 2 seconds memory limit per test 256 megabytes input st ...

  2. Code Forces Bear and Forgotten Tree 3 639B

    B. Bear and Forgotten Tree 3 time limit per test2 seconds memory limit per test256 megabytes inputst ...

  3. 2021/10/24 2021ICPC江西省赛 部分个人题解 A,B,H,K,L,J

    K Many Littles Make a Mickle 题目大意:有t组输入,每组输入一个n,一个m,表示有n层,第i层有i*i个房间,每个房间有m个人,求有多少人. 题解:数据小,暴力求和即可(也 ...

  4. 题解 CF 1413B A New Technique

    原题 题面简化 TTT 组数据 用 nnn 行.mmm 列的不重数字按输入顺序组成一个矩阵 数据范围 1≤T≤1000001≤T≤1000001≤T≤100000 1≤n,m≤5001≤n,m≤500 ...

  5. CSUST选拔赛题解之-Problem H: 逃出监狱

    Problem H: 逃出监狱 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 116  Solved: 42 [Submit][Status][Web ...

  6. CF Gym102059 H. Fractions

    题目要求找到给定区间的化简后分子分母的和小于1000的数字的个数 我的想法是先找到所有的满足要求的最简分数(总数不超过1e6,而且远小于),然后对询问查找每个最简分数出现的次数. #include&l ...

  7. [题解]CF Round #386 (Div.2)

    747A:Display Size 题意简述 给你 n n,求一对x,yx,y使得 x∗y=n x \ast y=n并且 x,y x,y最接近. 数据范围 n≤106 n \leq 10^6 思路 从 ...

  8. 图论 ---- E. Bear and Forgotten Tree 2(判补图的联通性技巧 图遍历的优化 条件拆分)

    题目大意 题目大意: 给你nnn个点,mmm对关系表示(ai,bi)(a_i,b_i)(ai​,bi​)之间是没有边的问你能否构建出一颗树满足111号点的度数为kkk? 解题思路: 如果没有后面的条件 ...

  9. CodeForces 658C Bear and Forgotten Tree 3(构造)

    题意:构造一棵树,有N个点,直径为d,深度为h 思路:首先构造一个长度为d的链,然后把其中一个距离边上为h的点变为根.然后我们就不停的在距离根为h上面的那一点不停的加点就好了,使得新加入的点的距离也为 ...

最新文章

  1. java内存模型和线程安全
  2. Web学习第一天:Servlet+JSP简单Demo
  3. 实战:Nginx集成Lua脚本并调用memcached
  4. stl max函数_std :: max_element()函数以及C ++ STL中的示例
  5. 22号大更新网站大面积降权的原因分析
  6. hbase常识及habse适合什么场景
  7. Word 里面如何设置多级标题
  8. php超小免杀大马_2019年最新免杀PHP大马(过D盾,过安全狗)
  9. js操作浏览器cookie详解
  10. 小牛叔讲Python第11章:函数的高级用法以及匿名函数
  11. WiFi 5:802.11ac 白皮书
  12. Android12华为,谷歌“神助攻”!Android12将不支持华为手机,鸿蒙迎来新挑战
  13. JWT手动签发| 自动签发
  14. 系统架构设计师(截图+做题思路+目录)
  15. Oracle 官网登录账号
  16. 普通上班族搞什么副业能赚钱?
  17. windows下使能/关闭硬件
  18. 云导播台php源码,云导播台使用指南
  19. 前端中关于下载文件问题
  20. 计算机应用当兵分配到哪,小编告诉你参军后的去向是如何确定的

热门文章

  1. 大数据WEB阶段Spring框架 AOP面向切面编程(二)
  2. 【Tiny4412】Tiny4412烧写uboot脚本分析
  3. 【Tools】vim YouCompleteMe自动补全配置与使用
  4. 【Linux】一步一步学Linux——dpkg-split命令(274)
  5. 【Linux】一步一步学Linux——printf命令(204)
  6. 【Linux】一步一步学Linux——chkconfig命令(148)
  7. 怪物刷新时间计时_热血传奇;散人对这类怪物可谓是情有独钟
  8. Delphi7的控件安装与删除
  9. hhc.exe制作chm
  10. idea单行注释对齐修改Settings - Editor - Code Style-Code Generation,取消comment code的勾选