zoukankan      html  css  js  c++  java
  • 题解[P4350Export Estimate]

    原题链接

    题意:
    给定一张无向连通图,每次询问时保留边权 (geq t) 的边,并对这张图进行如下操作:

    • 从小到大枚举每个点 (i) ,若其度数为 (0) 直接删去。
    • 若其度数为 (2) ,则找出连向 (i) 的点 (u,v)(可能相同),并删去点 (i) 以及连向 (u,v) 的两条边,再添加 (u,v) 一条边。((u,v) 相同时形成一个自环)

    ( ext{Sulotion})

    如果将询问按 (t) 从大到小排序,那每次需要的图就由之前的加上一些边得到,边权递减。

    先考虑每个操作流程对点与边的影响。

    设一个度数为 (k) 的点称为 (k) 度点。则可以发现在第一、第二个流程中受影响的点仅有 (0) 度点与 (2) 度点。

    每个 (0) 度点会将点的总量减 (1) ,而每个 (2) 度点会将点总数减 (1) ,且将边总数减 (1) 。而每个对 (2) 度点的操作不会影响其他点的度数。

    所以只需统计出 (0) 度点与 (2) 度点的个数 (sum_0,sum_2) ,以及出现过得边的个数 (edg) 。那总点数就是 (n-sum_0-sum_2), 总边数就是 (edge-sum_2) 。由于是动态加边,可以用并查集维护连通块内 (2) 度点与 (0) 度点个数。

    但事实上并非如此,在某个连同图是一个单纯的环时会出现问题。

    因为按照上文说法这个环会没有点剩余,而环上所有点都为 (2) 度点。但它最终剩余的是一个自环,点数与变数要加上 (1) 。设纯环个数为 (k),则最终点与边数为 (n-sum_0,-sum_2+k)(edge-sum_2+k)

    而由于纯环上所有点都为二度点,并查集同时维护点的个数后是容易判定的。

    时间复杂度 (O(nalpha(n)))

    代码:(个人认为实现方法还算简单)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e5+10;
    int n,m,s,x,y,v,ax,ay;
    int s_nd2,s_nd0,s_cyc;
    struct node{
    	int x,y,w;
    	bool operator <(const node &x)const{return w>x.w;}
    }e[N],q[N],ans[N];
    int f[N],sz[N],sz2[N],deg[N];bool cyc[N];char ch;
    inline int getf(int x){while(x^f[x])x=f[x]=f[f[x]];return x;}
    inline void read(int &x){
    	x=0;ch=getchar();while(ch<48)ch=getchar();
    	while(ch>47)x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    }
    void write(int x){if(x>9)write(x/10);putchar(48+x%10);}
    main(){
    	read(n),read(m);register int i,j=0,s,t;
    	for(i=1;i<=m;++i)read(x),read(y),read(v),e[i]=(node){x,y,v};
    	read(s);for(i=1;i<=s;++i)read(v),q[i]=(node){i,0,v};
    	sort(e+1,e+m+1);sort(q+1,q+s+1);
    	s_nd0=n;
    	for(i=1;i<=n;++i)sz[i]=1,f[i]=i;
    	for(i=1;i<=s;++i){
    		while(e[j+1].w>=q[i].w&&j<m){
    			++j;
    			x=e[j].x,y=e[j].y;ax=getf(x),ay=getf(y);
    			if(!deg[x])--s_nd0;if(deg[x]==2)--s_nd2,--sz2[ax];
    			if(!deg[y])--s_nd0;if(deg[y]==2)--s_nd2,--sz2[ay];
    			++deg[x];++deg[y];
    			s_cyc-=cyc[ax];cyc[ax]=0;
    			if(ax^ay)f[ay]=ax,s_cyc-=cyc[ay],sz[ax]+=sz[ay],sz2[ax]+=sz2[ay];
    			if(deg[x]==2)++s_nd2,++sz2[ax];
    			if(deg[y]==2)++s_nd2,++sz2[ax];
    			if(sz2[ax]==sz[ax])cyc[ax]=1,++s_cyc;
    		}
    		ans[q[i].x]=(node){n-s_nd0-s_nd2+s_cyc,j-s_nd2+s_cyc};
    	}
    	for(i=1;i<=s;++i)write(ans[i].x),putchar(' '),write(ans[i].y),putchar('
    ');
    }
    
  • 相关阅读:
    echarts做飞线图
    git 检出项目部分目录(稀疏检出)
    nuxt.js引入客户端脚本和第三方库出现window/document/ navigator未定义问题
    防止重复发送 Ajax 请求
    利用CSS、JavaScript及Ajax实现图片预加载的三大方法
    JavaScript中this的指向问题
    掌握jQuery插件开发
    原生javascript实现图片放大镜效果
    javascript实现页面滚屏效果
    JavaScript利用闭包实现模块化
  • 原文地址:https://www.cnblogs.com/Y-B-X/p/15440977.html
Copyright © 2011-2022 走看看