题解:P17524 [ECUSTPC 2026 Fall] 净化行动 3
每次拿取炮的时候一定是从中间开始拿,再那两边的,所以是拓扑排序。
如果某一行或某一列的炮
如果某一行或某一列的炮
如果某一行或某一列的炮
最后做一遍拓扑排序。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int T,n,in[N];
map<int,vector<int> > x,y;
pair<int,int> p[N];
vector<int> v[N];
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> T;
while (T--){
cin >> n;
x.clear(); y.clear();
for (int i = 1;i <= n;i++){
v[i].clear();
in[i] = 0;
}
for (int i = 1;i <= n;i++){
cin >> p[i].first >> p[i].second;
x[p[i].first].push_back(i);//列
y[p[i].second].push_back(i);//行
}
bool flag = 0;
for (auto i : x){
if (i.second.size()>3){//存在环
cout <<"NO\n";
flag = 1;
break;
}
if (i.second.size() > 2){
int q1 = p[i.second[0]].second;
int q2 = p[i.second[1]].second;
int q3 = p[i.second[2]].second;
int zuo = min({q1,q2,q3});
int you = max({q1,q2,q3});
if (q1 > zuo && q1 < you){//如果q1是炮架
v[i.second[0]].push_back({i.second[1]});
v[i.second[0]].push_back({i.second[2]});
}
if (q2 > zuo && q2 < you){//如果q2是炮架
v[i.second[1]].push_back({i.second[0]});
v[i.second[1]].push_back({i.second[2]});
}
if (q3 > zuo && q3 < you){//如果p3是炮架
v[i.second[2]].push_back({i.second[0]});
v[i.second[2]].push_back({i.second[1]});
}
}
}
if (flag) continue;
for (auto i : y){
if (i.second.size()>3){
cout <<"NO\n";
flag = 1;
break;
}
if (i.second.size() > 2){
int q1 = p[i.second[0]].first;
int q2 = p[i.second[1]].first;
int q3 = p[i.second[2]].first;
int zuo = min({q1,q2,q3});
int you = max({q1,q2,q3});
if (q1 > zuo && q1 < you){
v[i.second[0]].push_back({i.second[1]});
v[i.second[0]].push_back({i.second[2]});
}
if (q2 > zuo && q2 < you){
v[i.second[1]].push_back({i.second[0]});
v[i.second[1]].push_back({i.second[2]});
}
if (q3 > zuo && q3 < you){
v[i.second[2]].push_back({i.second[0]});
v[i.second[2]].push_back({i.second[1]});
}
}
}
if (flag) continue;
for (int i = 1;i <= n;i++){//统计入度
for (auto j : v[i]){
in[j]++;
}
}
queue<int> q;
for (int i = 1;i <= n;i++){
if (in[i] == 0){
q.push(i);
}
}
int qwq = 0;
while (!q.empty()){
int u = q.front();
q.pop();
qwq++;
for (auto i : v[u]){
in[i]--;
if (in[i] == 0){
q.push(i);
}
}
}
if (qwq != n){
cout <<"NO\n";
flag = 1;
}
if (flag) continue;
cout << "YES\n";
}
return 0;
}