zoukankan      html  css  js  c++  java
  • luogu1197 [JSOI2008]星球大战

    题目大意

      有一个无向图,每次删除一个节点,求删除后图中连通块的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)

    题解

      连通块?用并查集可以找到一个连通块,但是并查集不支持删除呀!所以我们将删点改为造点并连边就可以用并查集解决这个问题了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int MAX_EDGE = 200010, MAX_NODE = MAX_EDGE * 2;
    int TotNode, TotEdge;
    
    struct Node;
    struct Edge;
    
    struct Edge
    {
        Node *To;
        Edge *Next;
    }_edges[MAX_EDGE * 2];
    int _eCount;
    
    struct Node
    {
        Node *Father;
        Edge *Head;
        int AddRank;
        bool Built;
    }_nodes[MAX_NODE], *AddOrder[MAX_NODE];
    int Ans[MAX_NODE];
    
    void AddEdge(Node *from, Node *to)
    {
        Edge *e = _edges + _eCount++;
        e->To = to;
        e->Next = from->Head;
        from->Head = e;
    }
    
    void Build(int uId, int vId)
    {
        AddEdge(_nodes + uId, _nodes + vId);
        AddEdge(_nodes + vId, _nodes + uId);
    }
    
    Node *FindRoot(Node *cur)
    {
        return cur->Father == cur ? cur : cur->Father = FindRoot(cur->Father);
    }
    
    void Init(int n)
    {
        for (int i = 0; i < n; i++)
            _nodes[i].Father = _nodes + i;
    }
    
    bool Join(Node *a, Node *b)
    {
        Node *root1 = FindRoot(a), *root2 = FindRoot(b);
        if (root1 == root2)
            return false;
        else
        {
            root1->Father = root2;
            return true;
        }
    }
    
    bool Cmp(Node *a, Node *b)
    {
        return a->AddRank < b->AddRank;
    }
    
    int main()
    {
        scanf("%d%d", &TotNode, &TotEdge);
        for (int i = 0; i < TotEdge; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            Build(u, v);
        }
        int attackCnt;
        scanf("%d", &attackCnt);
        for (int i = 0; i < attackCnt; i++)
        {
            int v;
            scanf("%d", &v);
            _nodes[v].AddRank = attackCnt - i;
        }
        for (int i = 0; i < TotNode; i++)
            AddOrder[i] = _nodes + i;
        sort(AddOrder, AddOrder + TotNode, Cmp);
        int setCnt = 0;
        Init(TotNode);
        for (int i = 0; i < TotNode; i++)
        {
            AddOrder[i]->Built = true;
            setCnt++;
            for (Edge *e = AddOrder[i]->Head; e; e = e->Next)
                if (e->To->Built)
                    setCnt -= Join(AddOrder[i], e->To);
            Ans[i]=setCnt;
        }
        for (int i = TotNode - 1; i >= TotNode - attackCnt - 1; i--)
            printf("%d
    ", Ans[i]);
        return 0;
    }
    

      

  • 相关阅读:
    IIS安装和使用(Windows Server 2003)
    五险一金
    CKEditor与CKFinder的配置(ASP.NET环境)
    spring的@ConditionalOnMissingBean注解
    spring的@Primary注解
    java8实现接口需要重写接口中的default方法吗
    消息队列的作用
    ES快速入门,ElasticSearch 搜索引擎
    spring的@PostConstruct 和 @PreDestroy 注解
    Spring注解@Component、@Repository、@Service、@Controller区别
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9439544.html
Copyright © 2011-2022 走看看