[BZOJ4452] Export Estimate

对于所有度数为2的点会使点数减1,边数减1

然而需要特判简单环

我们把询问和边都从大到小排序,然后冰炸鸡维护

Ans_N=n-出度为0的点-出度为2的点+简单环,Ans_M=添加的边数-出度为2的点+简单环

 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 }
View Code

 

posted @ 2016-05-30 20:48  Ngshily  阅读(350)  评论(0编辑  收藏  举报