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 ...
随机推荐
- Noip模拟66 2021.10.2
T1 接力比赛 思路就是直接做背包$dp$,然后看看容量相同的相加的最大值. 考虑如何在$dp$过程中进行优化 注意到转移方程的第二维枚举容量没有必要从容量总和开始枚举 那么我们便转移边统计前缀和,从 ...
- Noip模拟41 2021.8.16
T1 你相信引力吗 对于区间的大小关系问题,往往使用单调栈来解决 这道题的优弧和劣弧很烦,考虑将其等价的转化 由于所有的合法情况绕过的弧都不会经过最高的冰锥, 又因为环可以任意亲定起点,这样可以直接把 ...
- 零基础学习Linux必会的60个常用命令
Linux必学的60个命令Linux提供了大量的命令,利用它可以有效地完成大量的工 作,如磁盘操作.文件存取.目录操作.进程管理.文件权限设定等.所以,在Linux系统上工作离不开使用系统提供的命令. ...
- 深度解析HashMap集合底层原理
目录 前置知识 ==和equals的区别 为什么要重写equals和HashCode 时间复杂度 (不带符号右移) >>> ^异或运算 &(与运算) 位移操作:1<&l ...
- 设计模式(1-2)-动态代理(newProxyInstance)
上节设计模式(1-1)-代理模式,讲了代理模式的静态代理与动态代理的写法.本节,会从Proxy.newProxyInstance() 这个方法开始讲,上一节文末的那个class文件怎么一步步的来的. ...
- hdu 1501 Zipper(DP)
题意: 给三个字符串str1.str2.str3 问str1和str2能否拼接成str3.(拼接的意思可以互相穿插) 能输出YES否则输出NO. 思路: 如果str3是由str1和str2拼接而成,s ...
- hdu 5102 The K-th Distance (队列+生成法,,)
题意: N个点的一棵树.定义点u和点v的距离等于它们之间的路径(唯一的)的长度.这样我们可以得到n*(n-1)/2个距离. 将它们从小到大排序,问前K个数的和是多少. 思路: 将边长为1的树枝都入队列 ...
- Linux Kernel 記憶體管理機制之美<转>
转自--http://five.rdaili.com/sohu.com.php?u=Mq3EniVnae0axim7jkGhH0IhA9uho6CQso7R1aYomXWJ9UemfwUQYmKRc8 ...
- ELK集群之filebeat(6)
filebeat工作原理 ilebeat是本地文件的日志数据采集器. 作为服务器上的代理安装,Filebeat监视日志目录或特定日志文件,tail file,并将它们转发给Elasticsearch或 ...
- JMeter跨线程组保持登录(多线程组共享cookie)
使用__setProperty设置全局变量: 1.jmeter中创建一个登录请求,然后执行,察看结果树-->查看返回cookie信息,我的是在Response data中的 Response h ...