Codeforces Round #736 (Div. 2) C. Web of Lies(思维、图)

  • 题目:Web of Lies

  • 题意:给出一张n个结点,m条边的无向图(结点编号为该点权值),可以进行加边、删边、查询操作,查询操作:若任意一点存在其邻边结点比其权值大,该点将会消失(包括其所有邻边)(从权值最小的结点开始依次消失),问最后能剩下的结点个数。
  • ps:每次查询结束后,图的状态仍然是查询前的状态。
  • 解析:根据题目数据量我们不可能每次查询都将图进行一次遍历,所以我们考虑每加一条边、删一条边对整张图的影响:
    1. 加边:权值较小点在加边操作前不存在其它比其权值大的点(邻接点),那么小点肯定会被删除,若存在比其大的其他邻接点,说明之前已经在需要删除的结点数量中计算过它;
    2. 删边:权值较小点在删边操作后不存在其它比其权值小的点,则可从需要删除的结点数量中进行恢复,否则不进行恢复,因为仍然有比它大的结点,它还是会被删。
  • 代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 2e5 + 5;
int cnt[N]; //结点u邻边中比结点u权值大的结点个数
int num = 0; //需要被删除的点的数量
int n, m, q;

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        if(u > v) swap(u, v);
        if(!cnt[u]) //之前结点u的邻边不存在比其大的结点
            num ++;
        cnt[u] ++;
    }
    cin >> q;
    while(q --)
    {
        int op, u, v;
        cin >> op;
        if(op == 1) //add
        {
            cin >> u >> v;
            if(u > v) swap(u, v);
            if(!cnt[u]) //之前结点u的邻边不存在比其大的结点
                num ++;
            cnt[u] ++;
        }
        else if(op == 2) //delte
        {
            cin >> u >> v;
            if(u > v) swap(u, v);
            cnt[u] --;
            if(!cnt[u]) //删除该边后, 结点u的邻边不存在比其大的结点
                num --;
        }
        else if(op == 3) //query
            cout << n - num << endl;
    }
    return 0;
}

posted @ 2021-08-03 11:16  ~K2MnO4  阅读(195)  评论(0)    收藏  举报