多校第四场——1007 Go Running

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;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值