Codeforces 611H - New Year and Forgotten Tree(二分图多重匹配)
首先我们将所有十进制下位数相同的点看作一种颜色,这样题目转化为,给定 \(m\le 6\) 种颜色、每种颜色的点的个数 \(b_i\) 以及每两种颜色之间连的边的条数 \(c_{i,j}\),要求构造出一棵符合要求的树。
考虑怎样解决上面的问题,这里有一个结论,对于每种颜色我们钦定一个点为“关键点”(方便起见,对于颜色 \(i\),我们钦定 \(10^{i-1}\) 为第 \(i\) 种颜色的关键点),那么,如果存在合法的树,一定存在一种情况,使得任意一条边都有一个点为关键点。至于证明,不太会严谨证明,不过大概想想应该可以想通,大概就是对于每条边 \((u,v)\),如果 \(u,v\) 都不是关键点,那么可以将 \(u\) 改接到 \(v\) 的颜色的关键点,或者将 \(v\) 改接到 \(u\) 的颜色的关键点,总能找到一种调整方法使得不存在 \(u,v\) 都不是关键点的边 \((u,v)\)。
不难发现对于符合上面的条件的图,如果只考虑 \(m\) 个关键点,那么这 \(m\) 个点形成的图也是一棵 \(m\) 个点的树,由于 \(m\) 很小,因此考虑根据 prufer 序列将这 \(m^{m-2}\) 棵树枚举一遍,接下来考虑怎样检验对于一棵关键点的生成树,是否存在一种将非关键点连向关键点的方案,使得对于任意两种颜色 \(i,j\),\(i,j\) 之间连的边数恰为 \(c_{i,j}\),我们不妨将这个问题转化一下,可以得到如下的模型:
- 对于每种颜色,共有 \(b_i-1\) 个非关键点,对于这 \(b_i-1\) 个关键点中的每一个点 \(u\),我们都要选择一种颜色 \(j\),并将 \(u\) 连向 \(j\) 的关键点,这样会使得 \(u,j\) 间边的个数多 \(1\)。
- 对于每个颜色之间的二元组 \((i,j)\) 都还需连 \(a_{i,j}\) 条边,其中 \(a_{i,j}\) 为 \(c_{i,j}\) 减去 \(i,j\) 在枚举的生成树上是否存在边。
敏感的同学应该可以发现,这不就一个二分图多重匹配吗?我们将所有颜色对 \((i,j)\) 看作左部点,连一条从源点像这样的 \((i,j)\),容量为 \(a_{i,j}\) 的边,所有颜色 \(i\) 看作右部点,连一条从 \(i\) 到汇点,容量为 \(b_i-1\) 的边,然后检验这张图是否存在完备匹配即可。输出方案就 dinic 跑遍最大流即可。时间复杂度 \(\mathcal O(\text{能过})\)。
const int MAXV=30;
const int MAXE=300*2;
const int INF=0x3f3f3f3f;
int n,m,p[8],q[8],cnt[8];
int S=29,T=30,hd[MAXV+5],to[MAXE+5],nxt[MAXE+5],cap[MAXE+5],ec=1;
void init(){memset(hd,0,sizeof(hd));ec=1;}
void adde(int u,int v,int f){
to[++ec]=v;cap[ec]=f;nxt[ec]=hd[u];hd[u]=ec;
to[++ec]=u;cap[ec]=0;nxt[ec]=hd[v];hd[v]=ec;
} int dep[MAXV+5],now[MAXV+5];
bool getdep(){
memset(dep,-1,sizeof(dep));dep[S]=0;
queue<int> q;q.push(S);now[S]=hd[S];
while(!q.empty()){
int x=q.front();q.pop();
for(int e=hd[x];e;e=nxt[e]){
int y=to[e],z=cap[e];
if(!~dep[y]&&z){
dep[y]=dep[x]+1;
q.push(y);now[y]=hd[y];
}
}
} return ~dep[T];
}
int getflow(int x,int f){
if(x==T) return f;int ret=0;
for(int &e=now[x];e;e=nxt[e]){
int y=to[e],z=cap[e];
if(dep[y]==dep[x]+1&&z){
int w=getflow(y,min(f-ret,z));
cap[e]-=w;cap[e^1]+=w;ret+=w;
if(ret==f) return ret;
}
} return ret;
}
int dinic(){
int ret=0;
while(getdep()) ret+=getflow(S,INF);
return ret;
}
int num[8][8],cc[8][8],pru[8],deg[8],vis[8];
void solve(){
memset(deg,0,sizeof(deg));
memset(vis,0,sizeof(vis));
memset(cc,0,sizeof(cc));
for(int i=1;i<=m-2;i++) deg[pru[i]]++;
for(int i=1;i<=m-2;i++){
int pos=0;
for(int j=1;j<=m;j++){
if(!deg[j]&&!vis[j]){pos=j;break;}
} cc[min(pos,pru[i])][max(pos,pru[i])]++;
// eprintf("%d %d\n",pos,pru[i]);
deg[pru[i]]--;vis[pos]=1;
} int u1=1,u2=m;
while(vis[u1]) u1++;
while(vis[u2]) u2--;
cc[u1][u2]++;
// eprintf("%d %d\n",u1,u2);
int cur=0;init();
for(int i=1;i<=m;i++) for(int j=i;j<=m;j++){
if(cc[i][j]>num[i][j]) return;cur++;
adde(S,cur,num[i][j]-cc[i][j]);
adde(cur,m*(m+1)/2+i,INF);
adde(cur,m*(m+1)/2+j,INF);
} for(int i=1;i<=m;i++) adde(m*(m+1)/2+i,T,cnt[i]-1);
if(dinic()==n-m){
for(int i=1;i<=m;i++) for(int j=i;j<=m;j++){
if(cc[i][j]) printf("%d %d\n",p[i],p[j]);
}
for(int i=1;i<=m;i++) q[i]=p[i];cur=0;
for(int i=1;i<=m;i++) for(int j=i;j<=m;j++){
cur++;
for(int e=hd[cur];e;e=nxt[e]){
int y=to[e],z=cap[e^1];
if(y==S) continue;
if(y-m*(m+1)/2==i){
while(z--) printf("%d %d\n",++q[i],p[j]);
} else {
while(z--) printf("%d %d\n",++q[j],p[i]);
}
}
}
exit(0);
}
}
void dfs(int x){
if(x==m-1) return solve();
for(int i=1;i<=m;i++) pru[x]=i,dfs(x+1);
}
int main(){
scanf("%d",&n);for(int cur=1;cur<=n;cur*=10) p[++m]=cur;
for(int i=1;i<m;i++) cnt[i]=p[i+1]-p[i];cnt[m]=n-p[m]+1;
for(int i=1;i<n;i++){
static char s1[9],s2[9];
scanf("%s%s",s1+1,s2+1);
int l1=strlen(s1+1),l2=strlen(s2+1);
if(l1>l2) l1^=l2^=l1^=l2;
num[l1][l2]++;
} if(m==1){
if(num[1][1]!=n-1) return puts("-1"),0;
for(int i=1;i<n;i++) printf("%d %d\n",i,i+1);
return 0;
} dfs(1);puts("-1");
return 0;
}
Codeforces 611H - New Year and Forgotten Tree(二分图多重匹配)的更多相关文章
- hihoCoder 1393 网络流三·二分图多重匹配(Dinic求二分图最大多重匹配)
#1393 : 网络流三·二分图多重匹配 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 学校的秋季运动会即将开始,为了决定参赛人员,各个班又开始忙碌起来. 小Hi和小H ...
- 【POJ 1698】Alice's Chance(二分图多重匹配)
http://poj.org/problem?id=1698 电影和日子匹配,电影可以匹配多个日子. 最多有maxw*7个日子. 二分图多重匹配完,检查一下是否每个电影都匹配了要求的日子那么多. #i ...
- 稳定的奶牛分配 && 二分图多重匹配+二分答案
题意: 农夫约翰有N(1<=N<=1000)只奶牛,每只奶牛住在B(1<=B<=20)个奶牛棚中的一个.当然,奶牛棚的容量有限.有些奶牛对它现在住的奶牛棚很满意,有些就不太满意 ...
- hiho 第117周 二分图多重匹配,网络流解决
描述 学校的秋季运动会即将开始,为了决定参赛人员,各个班又开始忙碌起来. 小Hi和小Ho作为班上的班干部,统计分配比赛选手的重任也自然交到了他们手上. 已知小Hi和小Ho所在的班级一共有N名学生(包含 ...
- 【网络流24题】No.7 试题库问题 (最大流,二分图多重匹配)
[题意] 假设一个试题库中有 n 道试题. 每道试题都标明了所属类别. 同一道题可能有多个类别属性.现要从题库中抽取 m 道题组成试卷.并要求试卷包含指定类型的试题. 试设计一个满足要求的组卷算法. ...
- POJ2584 T-Shirt Gumbo【二分图多重匹配】
题目链接: id=2584">http://poj.org/problem?id=2584 题目大意: 如今有5种型号(S.M.L.X.T)的衣服要发放给N个參赛队员.给出每一个參赛者 ...
- 网络流24题 第五题 - PowerOJ1740 CodeVS1905 圆桌问题 二分图多重匹配 网络最大流
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - PowerOJ1740 - 有SPJ - 推荐 题目传送门 - CodeVS1905 - 无SPJ - 0% ...
- [HihoCoder1393]网络流三·二分图多重匹配
题目大意: 班级有$N$名学生,运动会有$M$项不同的比赛,第$i$项比赛每个班需要派出$m_i$名选手参加,编号为i的学生最多同时参加给定的$b_i$项比赛中的任意$a_i$项比赛.根据统计的结果, ...
- hdu3605 Escape 二分图多重匹配/最大流
2012 If this is the end of the world how to do? I do not know how. But now scientists have found tha ...
随机推荐
- cunda 常用命令,删除,创建,换源
https://github.com/tensorflow/tensorflow/ conda create --name [虚拟环境名] python=3.7 创建一个环境 conda activa ...
- Idea Maven auto Import
- AIApe问答机器人Scrum Meeting 4.25
Scrum Meeting 2 日期:2021年4月25日 会议主要内容概述:前后端针对WebAPI进行协调与统一工作,商量接下来两日计划:敲定部分设计细节. 一.进度情况 组员 负责 两日内已完成的 ...
- PM技术分享——《构建之法》初步实践
软件理论 软件=程序+软件工程:软件开发活动(构建管理.源代码管理.软件设计.软件测试.项目管理)相关的内容的完成,才能完成把整个程序转化成为一个可用的软件的过程. 软件企业=软件+商业模式 软件开发 ...
- 开关电源(DC-DC)与LDO电源的区别---纹波
https://blog.csdn.net/edadoc2013/article/details/78435775
- 从零开始 DIY 智能家居 - 基于 ESP32 的智能紫外线传感器模块
目录 前言 硬件选择 二.使用步骤 获取代码 设备控制命令: 设备和协议初始化流程: 配置设备信息 回调函数注册 数据获取与上报流程 总结 前言 做了这么多传感器都是自己玩,这次家里人看不下去了,非得 ...
- index 首页
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- 【浏览器】聊聊DOM
[浏览器]聊聊DOM 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 作为前端开发,在以前的工作中大多是和DOM打交道,到 ...
- elasticsearch7.x配置文件
前言: 以下配置文件基于elasticsearch-7.13.4版本,当然也适用于其它7.x版本 集群环境: 部署3个节点的集群,各个节点不做角色区分,既是master,也是data,在性能 上这种方 ...
- 在 Node.js 中处理大 JSON 文件
在 Node.js 中处理大 JSON 文件 场景描述 问题一: 假设现在有一个场景,有一个大的 JSON 文件,需要读取每一条数据经过处理之后输出到一个文件或生成报表数据,怎么能够流式的每次读取一条 ...