ζ

CF1548A-Web of Lies

    题解

题目大意:给出一张没有重边的图,各个点的权值为它的编号。之后对这个图进行若干次操作。操作有一下三种:

  1. 选择两个点,在它们之间加一条边(保证这两个点之间原来没有边)
  2. 选择两个点,删除连接它们的边(保证这两个点之间原来有边)
  3. 对于每个点,如果与它直接相连的点权都大于它,就把这个点和由它引出的边都删掉。删了之后如果还有这样的点,就一直删,直到所有点都不满足“与它直接相连的点权都大于它”为止,输出剩下的点的数量。(每次3操作都是独立的,这些点被删掉之后会加回来)

对于操作三,如果一直删下去会发现:对于一个点,只有在初始状态下,与它直接相邻的点都比它的点权小,这个点最终才会剩下。对于每次3操作输出这样的点就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <bits/stdc++.h>
using namespace std;
set<int> son[200005];
bool vis[200005];
int main()
{
int n, m, i, j, u, v, res, o, _;
scanf("%d%d", &n, &m);
res = n;
for (i = 1; i <= m; i++)
{
scanf("%d%d", &u, &v);
son[u].insert(v);
son[v].insert(u);
}
for (i = 1; i <= n; i++)
{
if (!son[i].empty())
{
auto it = son[i].end();
it--;
if (*it > i)
{
vis[i] = 1;
res--;
}
}
}
scanf("%d", &_);
while (_--)
{
scanf("%d", &o);
if (o == 3)
{
printf("%d\n", res);
continue;
}
scanf("%d%d", &u, &v);
if (o == 2)
{
son[u].erase(v);
if (vis[u])
{
if (son[u].empty())
{
vis[u] = 0;
res++;
continue;
}
auto it = son[u].end();
it--;
if (*it < u)
{
res++;
vis[u] = 0;
}
}

son[v].erase(u);
if (vis[v])
{
if (son[v].empty())
{
vis[v] = 0;
res++;
continue;
}
auto it = son[v].end();
it--;
if (*it < v)
{
res++;
vis[v] = 0;
}
}
continue;
}
son[u].insert(v);
son[v].insert(u);
if (v > u && !vis[u])
{
vis[u] = 1;
res--;
}
if (u > v && !vis[v])
{
vis[v] = 1;
res--;
}
}
return 0;
}
页阅读量:  ・  站访问量:  ・  站访客数: