题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6808

思路:刚开始也是乱想,想几下就忍不住画个t-x图像,然后每个点有两种可能,一是向西跑,一是向东跑。在图中都画出来发现:

我画了4个点,箭头表示可能移动的方向,这时候发现这不就是找“覆盖所有点最少需要多少条直线”吗?我蠢的是刚开始就想到了这里,然后我忘了怎么找了,这种模板题当初学二分图时就做过,到了最后20分钟恍然大悟:把横纵坐标分别当做二分图的两边,把点所在的横纵坐标相连。因为我们把横纵坐标当做了二分图的点,二分图中的一个边就代表一个点。到这里就很清楚了,我们求的就是:选最少的点使得二分图中每条边都有端点被覆盖。最小点覆盖就是:选最少的点让二分图中每个边都有端点被选。最大匹配数 = 最小点覆盖。n = 1e5,肯定dinic,套个板子就行了。

咦?怎么知道点是不是在一条直线呢?直接旋转坐标系45度就行了。

x'=x·cos(θ)+y·sin(θ)

y'=y·cos(θ)-x·sin(θ)

我就直接用map哈希的,分配编号就行了。

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define lowbit(x) ((-x)&x)
#define met(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define bep(i, a, b) for(int i = a; i >= b; i--)
#define pb push_back
#define mp make_pair
#define debug cout << "KKK" << endl
#define ls num*2
#define rs num*2+1
#define re return
using namespace std;
const ll mod = 1e9 + 7;
const double PI = acos(-1);
const ll INF = 2e18+1;
const int inf = 1e9+5;
const double eps = 1e-10;
const int maxn = 2e5 + 5;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int rd(){
int x = 0; char ch = gc(); bool positive = 1;
for (; !isdigit(ch); ch = gc()) if (ch == '-') positive = 0;
for (; isdigit(ch); ch = gc()) x = x * 10 + ch - '0';
return positive ? x : -x;
}
map<double, int> vx, vy; ll dis[maxn];
int tot=1, cur[maxn],ne[maxn]; // tot初始化为1哦。 struct node {
int to,net;
long long val;
} p[maxn*2]; inline void add(int u,int v,long long w) {
p[++tot] = (node){v, ne[u], w};
ne[u] = tot;
} inline int bfs(int s, int t) {
for(register int i=1;i<=t;i++) dis[i]=inf;
queue<int> q;
q.push(s);
dis[s]=0;
cur[s]=ne[s];
while(!q.empty()) {
int x=q.front();
q.pop();
for(register int i=ne[x];i;i=p[i].net) {
int v=p[i].to;
if(p[i].val>0&&dis[v]==inf) {
q.push(v);
cur[v]=ne[v];
dis[v]=dis[x]+1;
if(v==t) return 1;
}
}
}
return 0;
} inline ll dfs(int x,long long sum,int t) {
if(x==t) return sum;
long long k,res=0;
for(register int i=cur[x];i&&sum;i=p[i].net) {
cur[x]=i;
int v=p[i].to;
if(p[i].val>0&&(dis[v]==dis[x]+1)) {
k=dfs(v,min(sum,p[i].val), t);
if(k==0) dis[v]=inf;
p[i].val-=k;
p[i^1].val+=k;
res+=k;
sum-=k;
}
}
return res;
} ll dinic(int s, int t){
ll ans = 0;
while(bfs(s, t)) {
ans+=dfs(s,inf, t);
}
return ans;
} int main(){
// ios::sync_with_stdio(false);
// cin.tie(0); cout.tie(0);
int T = rd();
double xx, yy, sq = sqrt(2)/2; //sq就是sin(θ)
int x, t, dx, dy;
int n, m, px, py;
while(T--){
vx.clear(); vy.clear();
n = rd(); tot = 1;
px = 0, py = n;
int st = 0, en= 2*n + 3; // 源点汇点
rep(i, 0, en) ne[i] = 0;
rep(i, 1, n){
x = rd();
t = rd();
xx = sq*(x + t);
yy = sq*(x - t); //旋转后的坐标
if(!vx.count(xx)) vx[xx] = ++px;
if(!vy.count(yy)) vy[yy] = ++py; // 分派编号
dx = vx[xx], dy = vy[yy];
add(dx, dy, 1);
add(dy, dx, 0); // 二分图建边
}
rep(i, 1, px){
add(st, i, 1);
add(i, st, 0); //源点建边
}
rep(i, n+1, py){
add(i, en, 1);
add(en, i, 0); //汇点建边
}
cout << dinic(st, en) << endl;
}
return 0;
}

2020杭电多校第四场 Go Running 最小点覆盖等于二分图最大匹配数的更多相关文章

  1. 杭电多校第四场 E Matrix from Arrays

    Problem E. Matrix from Arrays Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 ...

  2. 杭电多校第四场 Problem K. Expression in Memories 思维模拟

    Problem K. Expression in Memories Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262 ...

  3. [2019杭电多校第四场][hdu6623]Minimal Power of Prime

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6623 题目大意为求一个数的唯一分解的最小幂次.即120=23*31*51则答案为1. 因为数字太大不能 ...

  4. [2019杭电多校第四场][hdu6621]K-th Closest Distance(主席树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6621 题意为求区间[l,r]内第k小|a[i]-p|的值. 可以二分答案,如果二分的值为x,则判断区间 ...

  5. [2019杭电多校第四场][hdu6616]Divide the Stones

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6616 题意是说n个数分别为1-n,将n个数分成k堆,能否满足每堆个数相等,数值之和相等.保证n%k=0 ...

  6. [2019杭电多校第四场][hdu6614]AND Minimum Spanning Tree(贪心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6614 题目大意是有一张n个点的完全图,n个点点权为1-n,边权为两点点权按位与(&).求最小生 ...

  7. 2019杭电多校第四场hdu6623 Minimal Power of Prime

    Minimal Power of Prime 题目传送门 解题思路 先打\(N^\frac{1}{5}\)内的素数表,对于每一个n,先分解\(N^\frac{1}{5}\)范围内的素数,分解完后n变为 ...

  8. 杭电多校第四场-H- K-th Closest Distance

    题目描述 You have an array: a1, a2, , an and you must answer for some queries.For each query, you are g ...

  9. 2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)

    K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明 ...

  10. 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)

    以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...

随机推荐

  1. 数据脱敏java代码

    //前prefix后suffix脱敏 public static String idEncrypt(String number ,Integer prefix, Integer suffix) { i ...

  2. 解决动态class展示问题

    由于部分涉及到隐私,就打马赛克了 比如这个小问题,我有这个动态的class,里面是十几个类似btn的按钮,然后每个btn下面又有子多选框,一开始是我点击那个下面的子级他的父级就被选中,默认选中第一个父 ...

  3. 第三章:用python实现常用的用户分层模型(RFM模型)

    文章目录 项目背景 读取数据 数据分析 分析 Recent 分析 Frequency 分析 Mount RFM模型 分位数分层 自定义分层 定义客户标签 数据可视化 结论 源码地址 本文可以学习到以下 ...

  4. 解决ESP8266反复启动问题

    ESP8266刷不同固件后,有时会出现反复启动的问题,可能是FLASH里有未擦除干净的区域. 使用乐鑫 Flash 下载工具擦除 选好串口后点击erase擦除,即可正常使用

  5. 【python】绘图,颜色,线型

    颜色 最好用的:在网站上找到对应使用十六进制RGB/RGBA字符串表示颜色 可以看颜色及其对应色号名称:https://xkcd.com/color/rgb/ 参考:matplotlib指定绘图颜色的 ...

  6. Java Collection体系

    Collection 接口 宏观图 快速使用 import java.util.*; public class Demo { public static void main(String[] args ...

  7. nginx服务器下的TP5框架的虚拟域名配置

    server { listen 80; default_type 'text/html'; charset utf-8; server_name www.xxx.com; root /usr/loca ...

  8. Java下 BigDecimal类型数值的计算(转)

    BigDecimal bignum1 = new BigDecimal("40"); BigDecimal bignum2 = new BigDecimal("7&quo ...

  9. Flink笔记

    高可用(HA):直白来说就是系统不会因为某台机器,或某个实例挂了,就不能提供服务了.高可用需要做到分布式.负载均衡.自动侦查.自动切换.自动恢复等. 高吞吐: 单位时间内,能传输的数据量,对应指标就是 ...

  10. git在linux安装步骤详解!!

    linux上安装,以centos 7.x为例 yum命令安装 yum install gityum install 安装的git不是最新版本,如需最新版本需要自行编译 到下面的网站下载合适的版本 ht ...