AtCoder AGC037D Sorting a Grid (二分图匹配)
题目链接
https://atcoder.jp/contests/agc037/tasks/agc037_d
题解
这场D题终于不像AGC032D和AGC036D一样神仙了……
还是可做的吧 虽然考场上没好好想赛后直接看题解了= =
考虑倒推,首先谁都能看出来第二次操作之后要让每一行是这一行对应元素的一个排列;
这样的话我们可以把数\(i\)最后应在的行视为它的颜色,第二次操作就是要把所有颜色\(i\)的数挪到第\(i\)列。
那么第一次操作之后,我们就是要让每列是颜色的一个排列。
考虑二分图匹配模型:
最关键的思路是从左往右考虑每一列
左边对每一行建一个点,右边对每种颜色建一个点
如果当前还没考虑的部分里这一行有色\(j\), 那么连边\((i,j)\)
跑一遍Dinic确定这一行的颜色,然后下一行重复此过程
为什么这样一定能解出来?考虑对\(M\)归纳,还剩下\(M\)行、每种颜色恰有\(M\)个的时候,对于任何行的集合\(S\), 其所包括的颜色数显然不小于\(|S|\), 根据Hall定理,存在完美匹配,转化为\(M-1\)的情况。
简单分析可得时间复杂度\(O(N^{3.5})\) (Dinic二分图匹配复杂度为边数乘以点数的平方根,默认\(N,M\)同阶)
代码
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
namespace NetFlow
{
const int N = 202;
const int M = 40400;
const int INF = 1e7;
struct Edge
{
int v,w,nxt,rev;
} e[(M<<1)+3];
int fe[N+3];
int te[N+3];
int dep[N+3];
int que[N+3];
int n,en;
void addedge(int u,int v,int w)
{
// printf("addedge%d %d %d\n",u,v,w);
en++; e[en].v = v; e[en].w = w;
e[en].nxt = fe[u]; fe[u] = en; e[en].rev = en+1;
en++; e[en].v = u; e[en].w = 0;
e[en].nxt = fe[v]; fe[v] = en; e[en].rev = en-1;
}
bool bfs()
{
for(int i=1; i<=n; i++) dep[i] = 0;
int head = 1,tail = 1; que[tail] = 1; dep[1] = 1;
while(head<=tail)
{
int u = que[head]; head++;
for(int i=fe[u]; i; i=e[i].nxt)
{
if(dep[e[i].v]==0 && e[i].w>0)
{
dep[e[i].v] = dep[u]+1;
tail++; que[tail] = e[i].v;
}
}
}
return dep[2]!=0;
}
int dfs(int u,int cur)
{
if(u==2) {return cur;}
int rst = cur;
for(int i=te[u]; i; i=e[i].nxt)
{
if(dep[e[i].v]==dep[u]+1 && e[i].w>0 && rst>0)
{
int flow = dfs(e[i].v,min(rst,e[i].w));
if(flow>0)
{
e[i].w-=flow; e[e[i].rev].w += flow; rst-=flow;
if(e[i].w>0) {te[u] = i;}
if(rst==0) {return cur;}
}
}
}
if(cur==rst) {dep[u] = 0;}
return cur-rst;
}
void dinic(int _n)
{
n = _n;
int ret = 0;
while(bfs())
{
for(int i=1; i<=n; i++) te[i] = fe[i];
ret += dfs(1,INF);
}
// printf("ret=%d\n",ret);
}
void clear()
{
for(int i=1; i<=en; i++) e[i].v = e[i].w = e[i].nxt = e[i].rev = 0;
for(int i=1; i<=n; i++) dep[i] = fe[i] = que[i] = te[i] = 0;
n = en = 0;
}
}
using NetFlow::e;
using NetFlow::fe;
using NetFlow::addedge;
using NetFlow::dinic;
using NetFlow::clear;
const int N = 100;
int a[N+3][N+3];
int b[N+3][N+3];
vector<int> vec[N+3][N+3];
int tmp[N+3];
int n,m;
int getclr(int x) {return (x-1)/m+1;}
bool cmp(int x,int y) {return getclr(x)<getclr(y);}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) scanf("%d",&a[i][j]),vec[i][getclr(a[i][j])].push_back(a[i][j]);
for(int k=1; k<=m; k++)
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(vec[i][j].size()>0) {addedge(i+2,j+n+2,1);}
}
addedge(1,i+2,1);
addedge(i+n+2,2,1);
}
dinic(n+n+2);
for(int i=1; i<=n; i++)
{
int u = i+2;
for(int j=fe[u]; j; j=e[j].nxt)
{
int v = e[j].v-n-2;
if(v>0 && v<=n && e[j].w==0)
{
// printf("(%d,%d)\n",i,v);
b[i][k] = *vec[i][v].rbegin();
vec[i][v].pop_back();
}
}
}
clear();
}
for(int i=1; i<=n; i++) {for(int j=1; j<=m; j++) printf("%d ",b[i][j]); puts("");}
for(int j=1; j<=m; j++)
{
for(int i=1; i<=n; i++) tmp[i] = b[i][j];
sort(tmp+1,tmp+n+1,cmp);
for(int i=1; i<=n; i++) b[i][j] = tmp[i];
}
for(int i=1; i<=n; i++) {for(int j=1; j<=m; j++) printf("%d ",b[i][j]); puts("");}
return 0;
}
AtCoder AGC037D Sorting a Grid (二分图匹配)的更多相关文章
- Sorting Slides(二分图匹配——确定唯一匹配边)
题目描述: Professor Clumsey is going to give an important talk this afternoon. Unfortunately, he is not ...
- POJ 1486 Sorting Slides【二分图匹配】
题目大意:有n张幻灯片和n个数字,幻灯片放置有重叠,每个数字隶属于一个幻灯片,现在问你能够确定多少数字一定属于某个幻灯片 思路:上次刷过二分图的必须点后这题思路就显然了 做一次二分匹配后将当前匹配的边 ...
- POJ 1486 Sorting Slides(二分图匹配)
[题目链接] http://poj.org/problem?id=1486 [题目大意] 给出每张幻灯片的上下左右坐标,每张幻灯片的页码一定标在这张幻灯片上, 现在问你有没有办法唯一鉴别出一些幻灯片 ...
- POJ 1486 Sorting Slides(二分图完全匹配必须边)题解
题意:给你n张照片的范围,n个点的坐标,问你能唯一确定那几个点属于那几张照片,例如样例中4唯一属于A,2唯一属于C,1唯一属于B,3唯一属于C 思路:进行二分图完全匹配,怎么判断唯一属于?匹配完之后删 ...
- AtCoder Regular Contest 092 C - 2D Plane 2N Points(二分图匹配)
Problem Statement On a two-dimensional plane, there are N red points and N blue points. The coordina ...
- HDU 1507 Uncle Tom's Inherited Land*(二分图匹配)
Uncle Tom's Inherited Land* Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- POJ 2195 Going Home (带权二分图匹配)
POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...
- 【POJ】1486:Sorting Slides【二分图关键边判定】
Sorting Slides Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5390 Accepted: 2095 De ...
- POJ3020:Antenna Placement(二分图匹配)
Antnna Placement Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11093 Accepted: 5459 ...
随机推荐
- HTML5自学2
1.1 文字格式 一个杂乱无序.堆砌而成的网页,会让人感觉枯无味,而一个美观大方的网页,会让人有美轮美奂,流连忘返的感觉,本节将介绍如何设置网页文本格式. 文字格式包括字体.字号.文字颜色.字体风 ...
- Linux服务器Java进程突然消失排查办法
出处:JAVA进程突然消失的原因? 问题描述 在实际生产环境下,如果我们遇见Java进程突然消失,该如何去排查问题? 思路 可能有几种原因: ①.Java应用程序的问题:发生OOM导致进程Crash ...
- C# 面向对象8 值类型和引用类型
值类型和引用类型 概念 示意图: 1.值类型,在栈中开辟一块空间,存储 2.引用类型,在堆中开辟一块空间,存储数据,然在栈中开辟一块空间存储堆中的数据的地址
- Charles学习(二)之使用Map local代理本地静态资源以及配置网页代理在Mac浏览器上调试移动端
前言 我们在开发的过程肯定是一边写代码,一边查看自己的代码写的是否存在问题,那么问题来了,有两种情况 情况一:我们可以本地起服务,那么我们就可以在本地检查自己的代码,查看运行结果 情况二:本地无法起服 ...
- win10上面快捷方式如何放到桌面上
1.win+I 快捷方式调出windows设置 ,点击个性化. 2.进入个性化设置界面,点击主题 3.进入主题设置后,点击右边的相关的设置下的桌面图标设置 4.在弹出的窗口中,将我们希望看到 ...
- 一个页面多图表展示(四个div的方式)
效果如图所示,一个页面四个div,每个div里面展示相应的数据,因为这种效果会有点麻烦,而且不太雅观我就换了一种写法,一个div里面用四个图表,共用一个图例,先放上这个方式的效果图和源码,后期会再发布 ...
- linux 网卡配置详情
1.配置文件/etc/hosts(本地主机ip地址映射,可以有多个别名)./etc/services(端口号与标准服务之间的对应关系)./etc/sysconfig/network(设置主机名,网关, ...
- Lomsat gelral CodeForces - 600E (树上启发式合并)
You are given a rooted tree with root in vertex 1. Each vertex is coloured in some colour. Let's cal ...
- JAVA GUI设
1.两种设置大小的方式: //Border border1=BorderFactory.createEmptyBorder(20,20,20,20); //设置大小 panel.setB ...
- ESXi与物理交换机静态链路聚合配置过程中的小陷阱
作者:陆斌文章来自微信公众号:平台人生 内容简介:ESXi与物理交换机之间配置静态链路聚合时,因为静态链路聚合的特点,在进行down网卡和从虚拟交换机移除网卡的操作时,可能会无法完成故障流量切换,影响 ...