hdu4496(并查集+逆向思维)

传送门:hdu4496


题意:一个无向图图中共有n个点,一次给出m条边,要求输出一次删除前k(0<=k<m)条边后,该图中连通分量的个数。

思路:逆向思维,当没有边即k=m-1是共有n个连通分量,从后往前插入每条边,并查集判断是否有合并。


代码:

#include<bits/stdc++.h>
using namespace std;
#define FFF freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#define lson l,m,r<<1
#define rson m+1,r,r<<1|1
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define rep(i,l,r) for(int i=l;i<r;i++)
typedef long long ll;
typedef pair<int,int>pii;
typedef pair<ll,ll>pll;
typedef pair<double,double>pdd;
typedef pair<double,int>pdi;
const int INF=0x3f3f3f3f;
const int MOD=1000000007;
#define maxn 100010
struct edge{
    int from;
    int to;
}data[maxn];
int fa[maxn];
int n,m;
int ans[maxn];
void init()
{
    rep(i,0,n)fa[i]=i;
}
int Find(int r)
{
    return r==fa[r]?r:(fa[r]=Find(fa[r]));
}
bool Merge(int a,int b)
{
    int aa=Find(a);
    int bb=Find(b);
    if(aa!=bb)
        {
        fa[aa]=bb;
        return true;
        }
        return false;
}
int main()
{
//    ios::sync_with_stdio(false);
//    cin.tie(0);
//    #ifndef ONLINE_JUDGE
//    FFF
//    #endif // ONLINE_JUDGE
     while(~scanf("%d%d",&n,&m))
     {
         init();
         rep(i,0,m)
         scanf("%d%d",&data[i].from,&data[i].to);
         ans[m-1]=n;
         for(int i=m-1;i>0;i--)
         {
             if(Merge(data[i].from,data[i].to))
                ans[i-1]=ans[i]-1;
             else ans[i-1]=ans[i];
         }
         rep(i,0,m)printf("%d\n",ans[i]);
     }
    return 0;
}




猜你喜欢

转载自blog.csdn.net/reallsp/article/details/78218399