zoukankan      html  css  js  c++  java
  • 【BZOJ4452】[Cerc2015]Export Estimate 并查集

    【BZOJ4452】[Cerc2015]Export Estimate

    Description

    给你一个n个点m条边的无向图,每条边有权值,我们可以选择一个整数lim来生成一个新的图,过程如下: 
    1.先将原图中边权小于lim的边删掉 
    2.依次从1到n枚举每个点 
    (a)如果这个点没有边于它相连,这个点将会被删去 
    (b)如果这个点只与两条不相同的边x,y相连,设这两条边的另一个点分别为a,b,如果a,b和这个点都不相同(a,b可以相同),则依次做如下操作: 
    (i)删去边x,y 
    (ii)删去这个点 
    (iii)在a,b之间建立一条新的边 
    下面这个例子lim=95: 
     
    数据保证原图没有重边和自环,但不保证经过如上操作后的图没有重边和自环。 
    现在我们想知道当lim取若干值时,由原图生成的新图的点数和边数是多少。 

    Input

    第一行两个数n,m,表示原图有n点m条边。 
    接下来m行,每行三个数a,b,c,表示a和b之间有一条边权为c的双向边。 
    接下来一行一个数q,表示有q次询问。 
    接下来一行q个数,k1,k2,...,kq。 

    Output

    总共q行,每行两个数,表示lim取ki时,生成的新图的点数和边数 

    Sample Input

    Sample Input1:
    6 7
    1 2 20
    2 3 80
    2 5 100
    3 5 50
    3 4 100
    5 6 90
    4 6 100
    4
    25 75 85 95
    Sample Input2:
    10 14
    2 7 150
    1 2 100
    2 3 150
    3 1 200
    1 4 60
    4 5 20
    2 5 100
    5 6 90
    6 7 120
    7 5 130
    6 8 50
    8 9 200
    9 10 200
    10 7 200
    5
    300 50 95 100 110

    Sample Output

    Sample Output1:
    2 3
    1 1
    2 1
    4 2
    Sample Output2:
    0 0
    6 9
    4 5
    4 5
    5 4
    数据范围:
    1<=n<=300000
    1<=m<=300000
    0<=c<=300000
    1<=q<=300000
    0<=ki<=300000

    题解:发现在删除一个点的时候,其余点的度数不变,除了形成自环的情况,再结合几个例子就能发现:

    最后的点数=n-度数为0的点的个数-度数为2的点的个数+环数
    最后的边数=m-度数为2的点的个数+环数

    所以用并查集来维护有几个环即可,具体地,维护一个连通块中点的个数以及度数为2的点的个数,如果相等则说明这是一个环。

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=300010;
    int n,m,Q;
    int s0,s2,cir;
    struct node
    {
    	int a,b,c;
    }p[maxn];
    struct query
    {
    	int org,k;
    }q[maxn];
    int f[maxn],siz[maxn],sz[maxn],d[maxn],a1[maxn],a2[maxn];
    bool cmpc(const node &a,const node &b)
    {
    	return a.c>b.c;
    }
    bool cmpk(const query &a,const query &b)
    {
    	return a.k>b.k;
    }
    int find(int x)
    {
    	return (f[x]==x)?x:(f[x]=find(f[x]));
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i,j,a,b;
    	for(i=1;i<=m;i++)	p[i].a=rd(),p[i].b=rd(),p[i].c=rd();
    	sort(p+1,p+m+1,cmpc);
    	Q=rd();
    	for(i=1;i<=Q;i++)	q[i].org=i,q[i].k=rd();
    	sort(q+1,q+Q+1,cmpk);
    	for(i=1;i<=n;i++)	siz[i]=1,f[i]=i;
    	s0=n;
    	for(i=j=1;i<=m;i++)
    	{
    		for(;j<=Q&&q[j].k>p[i].c;j++)
    			a1[q[j].org]=n-s0-s2+cir,a2[q[j].org]=i-1-s2+cir;
    		s0-=(!d[p[i].a])+(!d[p[i].b]),s2-=(d[p[i].a]==2)+(d[p[i].b]==2);
    		a=find(p[i].a),b=find(p[i].b);
    		cir-=(siz[a]==sz[a])+(a!=b&&siz[b]==sz[b]);
    		sz[a]-=(d[p[i].a]==2),sz[b]-=(d[p[i].b]==2);
    		d[p[i].a]++,d[p[i].b]++;
    		s2+=(d[p[i].a]==2)+(d[p[i].b]==2);
    		sz[a]+=(d[p[i].a]==2),sz[b]+=(d[p[i].b]==2);
    		if(find(a)!=find(b))	siz[b]+=siz[a],sz[b]+=sz[a],f[a]=b;
    		cir+=(siz[b]==sz[b]);
    	}
    	for(;j<=Q;j++)	a1[q[j].org]=n-s0-s2+cir,a2[q[j].org]=m-s2+cir;
    	for(i=1;i<=Q;i++)	printf("%d %d
    ",a1[i],a2[i]);
    	return 0;
    }

     

     
  • 相关阅读:
    1、Python的初识与简介
    解密解密
    python看是32位还是64
    linux实战一段,安装python3(centos)
    前段技巧
    django后端safe和前端safe的方法
    测试
    python小知识整理
    ajax格式
    111
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7859648.html
Copyright © 2011-2022 走看看