题目链接: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. lua中定义变量用and和or连接

    原文链接 最近在写代码中看到lua定义变量有local a = value1 and value2的操作,有些疑问,在此记录一下:当连接两个操作数时,1.对于运算符and,假设它的第一个操作数为假,就 ...

  2. 接口自动化-pycharm下查看日志文件中文乱码

      如图: 方法:pycharm 进入setting,找到File Encodings将编码全部设置gbk 现在室这样的:    修改为: 再次看日志:

  3. Coursera Programming Languages, Part B 华盛顿大学 Homework 5

    这次 Week 2 的作业比较难,任务目标是使用 \(racket\) 给一个虚拟语言 \(MUPL\) (made-up programming language) 写一个解释器 所以单独开个贴来好 ...

  4. 2021/9/26 Leetcode 两数之和

    题目:给你两个整数 a 和 b ,不使用 运算符 + 和 - ​​​​​​​,计算并返回两整数之和. int getSum(int a, int b) { while(b != 0){ unsigne ...

  5. Mac下如何使用EVE-NG的telnet客户端和wireshark抓包

    当我没有安装SecureCRT,点击启动的设备,弹出使用终端打开,但是由于eve中telnet使用的url是telnet xx.xx.xx.xx:xxxx 的形式,其在终端app中不能正常工作,tel ...

  6. SpringBoot怎么管理封装java包的关系

    首先SpringBoot直接写注解加依赖就可以了,基本上不用写xml,非常方便,在这里我只写了两个核心包 为什么选择jar类型? SpringBoot基本上是个应用程序了,只要用java命令程序去运行 ...

  7. tensorflow 模型批处理参数tensor快速赋值参考

    批处理调用模型的时候,如果逐像素给tensor对象数据部分赋值的话,效率是很低的,尤其是对于一些图片数据,所以数据块直接拷贝可以大大提高效率, 先取得数据指针: output_tensor->f ...

  8. centeros忘记root登录密码

    转载自:https://www.cnblogs.com/dongml/p/10333819.html 很多时候我们都会忘记Linux root 用户的口令,下面就教大家如果忘记root口令怎么办 第1 ...

  9. 弹框tabel

    <el-dialog title="删除数据类型" :visible.sync="isDataType" width="60%" :b ...

  10. js数组原型方法

    今天学习了一下js数组原型的操作方法,小结一下学习地址https://www.cnblogs.com/obel/p/7016414.html 1.join() join(separator): 将数组 ...