码迷,mamicode.com
首页 > 其他好文 > 详细

HDU - 4496 City (逆向并查集)

时间:2018-08-03 16:20:52      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:个数   连接   检查   freopen   turn   pac   stdio.h   print   ini   

题意:有N个点M条边的无向图,每次删除一条边直到删完为止,求每一次删边操作之后,连通块的个数。

M<=1e5,N<=1e4。如果每次删边之后暴力求连通块肯定超时。换个思路,对一个N阶零图,我们用并查集表示每一个点为独立的连通块,然后每次加边后检查边连接的两点是否已在一个连通块中,以此求出每次加边后的连通块个数。

那么可以把删边的过程倒过来离线处理。

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn = 1e4+5;
const int INF= 0x3f3f3f3f;
struct OP{int u,v; }p[maxn*10];
int fa[maxn];
int ans[maxn*10];
void init(int N){ for(int i=0;i<=N;++i) fa[i]=i;}
inline int Find(int x){return fa[x]==x? x:fa[x]= Find(fa[x]);}
void Union(int a,int b){
    a = Find(a), b= Find(b);
    if(a!=b) fa[a]= b;
}

int main()
{
    #ifndef ONLINE_JUDGE
         freopen("in.txt","r",stdin);
         freopen("out.txt","w",stdout);
    #endif
    int T,N,M,Q,u,v,tmp,K,cas=1;
    while(scanf("%d%d",&N,&M)==2){
        init(N);
        for(int i=1;i<=M;++i) scanf("%d%d",&p[i].u,&p[i].v);
        int res=N;
        for(int i=M;i>=1;--i){
            int u = p[i].u, v= p[i].v;
            u = Find(u),v = Find(v);
            ans[i] = res;
            if(u!=v){
                Union(u,v);
                res--;
            }
        }
        for(int i=1;i<=M;++i) printf("%d\n",ans[i]);
    }
    return 0;
}

 

HDU - 4496 City (逆向并查集)

标签:个数   连接   检查   freopen   turn   pac   stdio.h   print   ini   

原文地址:https://www.cnblogs.com/xiuwenli/p/9414277.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!