🐱 个人理解
🍉 | 1.本题需要使用 AcWing 861. 二分图的最大匹配 和 AcWing 826. 单链表 的模板。
🍌 | 2.首先定义一些变量……
🦁 >>
flag
变量,代表🐼有没有说谎
🐯 >>st[N]
数组,代表当前点有没有被使用过
🐻 >>range[N]
数组,用来存储🐼给出的点
🦝 >>h[N]
、e[N]
、ne[N]
和idx
,是y总
邻接表的模板,如果我们发现🐼给出的点对有可能是相交的,就将它们加到这个邻接表中
🐸 >>color[N]
,用来存储二分图中的着色点(1
和2
)
🥝 | 3.必要的变量我们都准备好了,接下来我们读入数据,为了方便后续我们判断两边是不是有可能相交,保持点对中的first
是小于second
的,并且检查点对中的两个点是否已经被用过,如果都没有被用过则插入range[N]
数组中,并将二者都标记为true
;否则flag
设为false
,退出。
🍎 | 4.若读入的点对都是合法的,我们开始进行下一步处理。将range[N]
中的点对两两互相比较。假设第一个点对为l, r
,第二个点对为a, b
,如果我们我们发现l < a < r < b
或者a < l < b < r
,也就是说如果将⚪拉成一条线的话这两个点对是相交的,那么就说明它们在⚪上就有可能相交,在邻接表上插入对应点对在数组中的下标。
🍐 | 5.接下来我们开始使用二分图着色法,对于给定的这些点对构成的图,如果它们是能够二分的话,那么就说明它们互不相交,🐼说的是真话,直接使用二分模板即可。遍历点对数组range
,若发现当前遍历到的点对未被染色,则将其染为1
,并且新建一个数组q
,将其入队,随后遍历在上一步中我们建立的邻接表,检查与当前遍历到的点对相接的点对是否已被染色,若二者染色相同,则flag
设为false
,🐼说的是假话;否则将其染为另外一种颜色,并将其入队。若可二分,则🐼说的是真话。
🐶 注意点
🍕 | 1.一开始最大值设置成了2020
,但是TLE
了,反正这里也没有二维数组,索性将最大值设为10010
,AC
了。
🍔 | 2.建立邻接表这一步中我们需要建立的是一个无向图,即点对i
和点对j
它们两个之间既可以从i
出发找到j
,也可以从j
出发找到i
,这样才能保证二分图着色时能够正确遍历。
🐹 代码
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
typedef pair<int, int> pii;
const int N = 100010;
int n, m, h[N], e[N], ne[N], idx, color[N];
bool st[N];
struct Range {
int l, r;
}range[N];
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int main() {
cin >> n >> m;
bool flag = true;
for (int i = 0; i < m; i++) {
int a, b;
cin >> a >> b;
if (a > b) swap(a, b);
if (st[a] || st[b]) {
flag = false;
break;
}
st[a] = st[b] = true;
range[i] = {a, b};
}
if (flag) {
memset(h, -1, sizeof h);
for (int i = 0; i < m; i++) {
int l = range[i].l, r = range[i].r;
for (int j = i + 1; j < m; j++) {
int a = range[j].l, b = range[j].r;
if ((l < a && a < r && r < b) || (a < l && l < b && b < r)) {
add(j, i);
add(i, j);
}
}
}
for (int i = 0; i < m; i++) {
if (!color[i]) {
color[i] = 1;
queue<int> q;
q.push(i);
while (q.size()) {
int u = q.front();
q.pop();
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (!color[j]) {
color[j] = 3 - color[u];
q.push(j);
}
else if (color[j] == color[u]) {
flag = false;
break;
}
}
}
}
if (!flag) break;
}
}
if (flag) puts("panda is telling the truth...");
else puts("the evil panda is lying again");
return 0;
}