Problem Description
Zhang3 is the class leader. Recently she’s implementing a policy about long-distance running. This forces every student in her class to take a run.
There is a main road in the school from west to east, which can be regarded as an infinite axis, and its positive direction is east. Positions on the road are represented with numbers. In order to complete the task, each student must run along the main road. Each student can decide the following things:
- The time to start running.
- The time to finish running.
- The position to start running.
- The direction of running, which is either west or east.
Once these things are decided, the student will appear at the starting position on the road at the start time, then start running in the chosen direction at a speed of 1m/s. The student disappears at the finish time. Each student will only run once.
Zhang3 knows that some students are not following her policy, so she set up some monitors. According to technical issues, the monitors can only report that there’s at least one student at a certain place at a certain time. Finally Zhang3 received n reports.
Help Zhang3 determine the minimum possible number of students who have run.
Input
The first line of the input gives the number of test cases, T(1≤T≤100). T test cases follow.
For each test case, the first line contains an integer n(1≤n≤105), the number of reports.
Then n lines follow, the ith of which contains two integers ti,xi(1≤ti,xi≤109), representing that there’s at least one student at position xi(m) at time ti(s).
The sum of n in all test cases doesn’t exceed 5×105.
Output
For each test case, print a line with an integer, representing the minimum number of students who have run.
Sample Input
2
3
1 1
2 2
3 1
3
1 1
2 2
3 3
Sample Output
2
1
题意:有一些学生在 xx 轴上跑步,速度为 11 ,可以有两种方向,并且具有起始时间、结束时间和起始位置。现在有 nn 个监视器,每个监视器记录了 (t,x)(t,x),表示在t时刻, xx 位置有人。问最少有多少个学生有去跑步。
思路:把横纵坐标分别当做二分图的两边,把点所在的横纵坐标相连。这样的话,二分图中的一个边就代表一个点。即求最小点覆盖,即最大匹配。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const int inf = 0x3f3f3f3f;
vector<int> p[N << 1];
queue<int> q;
int x_c[N], y_c[N], x_d[N], y_d[N], a[N], b[N], d[N << 1];
int dis, V, len;
bool vis[N];
int get(int m)
{
return lower_bound(d + 1, d + 1 + len, m) - d;
}
bool Bfs()
{
while (!q.empty())
{
q.pop();
}
for (int i = 1; i <= len; i++)
{
x_d[i] = -1;
y_d[i] = -1;
}
dis = inf;
for (int i = 1; i <= len; i++)
{
if (x_c[i] == -1)
{
q.push(i);
x_d[i] = 0;
}
}
while (!q.empty())
{
int now = q.front();
q.pop();
if (x_d[now] > dis)
break;
for (int i = 0; i < p[now].size(); i++)
{
int t = p[now][i];
if (y_d[t] == -1)
{
y_d[t] = x_d[now] + 1;
if (y_c[t] == -1)
{
dis = y_d[t];
}
else
{
x_d[y_c[t]] = y_d[t] + 1;
q.push(y_c[t]);
}
}
}
}
return dis != inf;
}
int Dfs(int v)
{
for (int i = 0; i < p[v].size(); i++)
{
int t = p[v][i];
if (!vis[t] && y_d[t] == x_d[v] + 1)
{
vis[t] = 1;
if (y_c[t] != -1 && y_d[t] == dis)
continue;
if (y_c[t] == -1 || Dfs(y_c[t]))
{
y_c[t] = v;
x_c[v] = t;
return true;
}
}
}
return false;
}
int go()
{
int ans = 0;
for (int i = 1; i <= len; i++)
{
x_c[i] = -1;
y_c[i] = -1;
}
while (Bfs())
{
for (int i = 1; i <= len; i++)
{
vis[i] = false;
}
for (int i = 1; i <= len; i++)
{
if (x_c[i] == -1 && Dfs(i))
{
ans++;
}
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
{
int n;
int cnt = 0;
cin >> n;
for (int i = 1; i <= 2 * n; i++)
{
p[i].clear();
}
for (int i = 1; i <= n; i++)
{
cin >> a[i] >> b[i];
d[++cnt] = (a[i] + b[i]);
d[++cnt] = (a[i] - b[i]);
}
sort(d + 1, d + 1 + cnt);
len = unique(d + 1, d + 1 + cnt) - d - 1;
for (int i = 1; i <= n; i++)
{
int t1 = get(a[i] + b[i]);
int t2 = get(a[i] - b[i]);
p[t1].push_back(t2);
}
cout << go() << endl;
}
}