zoukankan      html  css  js  c++  java
  • 并查集--CSUOJ 1601 War

    并查集的经典题目:

    CSUOJ 1601: War

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 247  Solved: 70
    [Submit][Status][Web Board]

    Description

    AME decided to destroy CH’s country. In CH’ country, There are N villages, which are numbered from 1 to N. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected. To defend the country from the attack of AME, CH has decided to build some roads between some villages. Let us say that two villages belong to the same garrison area if they are connected.
    Now AME has already worked out the overall plan including which road and in which order would be attacked and destroyed. CH wants to know the number of garrison areas in his country after each of AME’s attack.

    Input

    The first line contains two integers N and M — the number of villages and roads, (2 ≤ N ≤ 100000; 1 ≤ M ≤ 100000). Each of the next M lines contains two different integers u, v (1<=u, v<=N)—which means there is a road between u and v. The next line contains an integer Q which denotes the quantity of roads AME wants to destroy (1 ≤ Q ≤ M). The last line contains a series of numbers each of which denoting a road as its order of appearance — different integers separated by spaces.

    Output

    Output Q integers — the number of garrison areas in CH’s country after each of AME's attack. Each pair of numbers are separated by a single space.

    Sample Input

    3 1
    1 2
    1
    1
    4 4
    1 2
    2 3
    1 3
    3 4
    3
    2 4 3

    Sample Output

    3
    1 2 3
     1 /*题目大意:n个点m条边(边1,边2...边m),q个要摧毁的边,求按顺序每摧毁一条边后图中连通块的个数
     2 
     3  
     4 
     5 题目分析:并查集,先找出最后状态,反向加边,先将q条路全部摧毁后的连通块个数求出来,然后加边即可,每加一条边,用并查集判断,若两点不在同一连通块中,则合并且连通块个数减1*/
     6 #include<cstdio>
     7 #include<cstring>
     8 #define N 100100
     9 struct Edge {
    10     int u,v;
    11 }edge[N];
    12 bool visited[N];
    13 int a[N],stack[N];
    14 int n,m,q,ans=0;
    15 int father[N];
    16 int find(int x)
    17 {
    18     return (father[x]==x)?father[x]:father[x]=find(father[x]);/*注意路径压缩和返回father[x]*/
    19 }
    20 void add_tu()
    21 {
    22     for(int i=1;i<=n;++i)
    23     father[i]=i;
    24     for(int i=1;i<=m;++i)
    25     {
    26         if(visited[i]) continue;
    27         int r1=find(edge[i].u);
    28         int r2=find(edge[i].v);
    29         if(r1!=r2)
    30         {
    31             father[r2]=r1;
    32             ans--;/*先把连通块的数目设为n,建图的过程中,边建边删除,也可以统计father[i]==i*/
    33         }
    34     }
    35     stack[q]=ans;/*当前的状态是q的状态,不能加边了*/
    36 }
    37 void add_edge()
    38 {
    39     for(int i=q-1;i>=1;--i)
    40     {
    41         int r1=find(edge[a[i+1]].u);/*注意加的这一条边是当前状态的后一条边,因为这个后一条边没有删除,而不是a[i],之前深受其害,连样例都过了*/
    42         int r2=find(edge[a[i+1]].v);
    43         if(r1!=r2)
    44         {
    45             father[r2]=r1;
    46             ans--;
    47             
    48         }
    49         stack[i]=ans;/*注意不要把这句放到if里面*/
    50     }
    51 }
    52 int main()
    53 {
    54     while(scanf("%d%d",&n,&m)!=EOF)/*注意这里不能只用scanf("%d%d",&n,&m),因为这样没法用^z结束程序*/
    55         memset(edge,0,sizeof(edge));
    56         memset(visited,false,sizeof(visited));/*别忘记初始化*/
    57         memset(a,0,sizeof(a));
    58         memset(stack,0,sizeof(stack));
    59         ans=n;
    60         for(int i=1;i<=m;++i)
    61         {
    62             scanf("%d%d",&edge[i].u,&edge[i].v);
    63         }
    64         scanf("%d",&q);
    65         for(int i=1;i<=q;++i)
    66         {
    67             scanf("%d",&a[i]);
    68             visited[a[i]]=true;/*把不访问的边设上标记*/
    69         }
    70         add_tu();
    71         add_edge();
    72         for(int i=1;i<=q-1;++i)
    73         printf("%d ",stack[i]);/*CSUOJ这个坑爹的OJ,多输出一个空格,就格式不对*/
    74         printf("%d
    ",stack[q]);
    75     }
    76     return 0;
    77 }
     
  • 相关阅读:
    软件工程个人作业01
    动手动脑
    大道至简感想终结篇
    课后作业
    反思
    课后作业
    不忘初心,方得始终
    课后作业
    沟通,让一切变得简单

  • 原文地址:https://www.cnblogs.com/c1299401227/p/5475918.html
Copyright © 2011-2022 走看看