HDU4496 D-City(并查集逆向思维)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4496

写在前边:期末考试忙的焦头烂额,平时没学习的后果啊,整理道题先。

题目大意:就是告诉你有n个城市,m条边,这个人每经过一条边会摧毁它,问你每摧毁一条边他剩下的连通块是多少(一开始所有的点都是连在一起的,且最后所有的点都是不连通的)

题目思路:正向的化会非常的麻烦,因为你无法确定某一个状态下摧毁的边是不是以前就摧毁过的。那么我们就可以逆向思考这个问题;你的最后一个状态肯定是N因为所有的边都被摧毁了,也就是说你摧毁了所有,然后倒着重建,重建过程中每当碰到不是一个集合的点,它的联通分量就会减一。

总结一下:1)结构体储存点与边

                  2)建立一个答案数组

                  3)ans[i]=sum,然后倒着维护sum值(每当碰到不在一个集合的情况下,sum--)


代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int pre[maxn];
struct node{
    int u;
    int v;
}p[maxn];
int ans[maxn];
void build()
{
    for(int i=0;i<maxn;i++)  pre[i]=i;
}
int Find(int x)
{
    int p,tmp;
    p=x;
    while(x!=pre[x]) x=pre[x];
    while(p!=x){
        tmp=pre[p];
        pre[p]=x;
        p=tmp;
    }
    return x;
}

bool join(int x,int y)
{
    int p=Find(x);
    int q=Find(y);
    if(p!=q){
        pre[p]=q;
        return false;//false为不是一个集合的情况
    }
    return true;
}

int main()
{
    int n,m;while(~scanf("%d%d",&n,&m)){
         build();
        memset(ans,0,sizeof(ans));
        for(int i=0;i<m;i++) scanf("%d%d",&p[i].u,&p[i].v);//初始化

        int sum=n;
        for(int i=m-1;i>=0;i--){
            ans[i]=sum;
            if(!join(p[i].u,p[i].v)) sum--;
        }
        for(int i=0;i<m;i++) printf("%d\n",ans[i]);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值