对于所有度数为2的点会使点数减1,边数减1
然而需要特判简单环
我们把询问和边都从大到小排序,然后冰炸鸡维护
Ans_N=n-出度为0的点-出度为2的点+简单环,Ans_M=添加的边数-出度为2的点+简单环
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 #define mp make_pair 5 #define fir first 6 #define sec second 7 #define maxn 300005 8 struct Road{ 9 int u,v,w; 10 bool operator<(Road t)const{ return w>t.w; } 11 }R[maxn]; 12 pair<int,int>qry[maxn],ans[maxn]; 13 int fa[maxn],sz[maxn],er[maxn],du[maxn]; 14 int n,m,q,zero,two,cir; 15 int gf(int x){ return fa[x]=fa[x]==x?x:gf(fa[x]); } 16 void un(int x,int y){ 17 fa[y]=x; 18 sz[x]+=sz[y],er[x]+=er[y]; 19 } 20 int add_du(int x){ 21 int f=gf(x); 22 if(du[x]==2){ 23 if(er[f]==sz[f])cir--; 24 two--,er[f]--; 25 } 26 if(!du[x])zero--; 27 du[x]++; 28 if(du[x]==2){ 29 two++,er[f]++; 30 if(er[f]==sz[f])cir++; 31 } 32 return f; 33 } 34 int main(){ 35 scanf("%d%d",&n,&m); 36 for(int i=1;i<=m;i++) 37 scanf("%d%d%d",&R[i].u,&R[i].v,&R[i].w); 38 sort(R+1,R+1+m); 39 scanf("%d",&q); 40 int x; 41 for(int i=1;i<=q;i++){ 42 scanf("%d",&x); 43 qry[i]=mp(x,i); 44 } 45 sort(qry+1,qry+1+q); 46 for(int i=1;i<=n;i++) 47 sz[i]=1,er[i]=0,fa[i]=i; 48 int lst=1; 49 zero=n,two=0,cir=0; 50 for(int i=q;i;i--){ 51 for(int j=lst;j<=m&&R[j].w>=qry[i].fir;j++,lst=j){ 52 int f1=add_du(R[j].u),f2=add_du(R[j].v); 53 if(f1!=f2)un(f1,f2); 54 } 55 ans[qry[i].sec]=mp((n-zero)-two+cir,(lst-1)-two+cir); 56 } 57 for(int i=1;i<=q;i++) 58 printf("%d %d\n",ans[i].fir,ans[i].sec); 59 return 0; 60 }