# AlenaNuna

## 树剖+线段树||树链剖分||BZOJ2238||Mst

  1 #include<cstdio>
2 #include<iostream>
3 #include<cstring>
4 #include<algorithm>
5 #include<cstdlib>
6 #define min(a,b) ((a)<(b)?(a):(b))
7 using namespace std;
8 const int maxn=50005,maxm=100005,maxw=10005,inf=1<<30;
9 int N,M,x,y,w,Q,edge_head[maxn],num_edge=0,edge_head2[maxn],num_edge2=0,fa[maxn],real_sum=0;
10 int size[maxn],son[maxn],seg[maxn],rev[maxn],f[maxn],dep[maxn],top[maxn],X,Y,_ans,T;
11 bool via[maxm],ans=1;
12 inline int rd(){
13     int x=0,f=1;char c=getchar();
14     while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
15     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
16     return f*x;
17 }
18 struct Edge{
19     int to,dis,nx,from;
20 }edge[maxm<<1];
21 struct Edge2{
22     int to,dis,nx,from,id;
23 }edge2[maxm];
24 inline void Add_edge(int from,int to,int dis){
25     edge[++num_edge].nx=edge_head[from];
26     edge[num_edge].from=from;
27     edge[num_edge].to=to;
28     edge[num_edge].dis=dis;
29     edge_head[from]=num_edge;
30     return;
31 }
32 inline void Add_edge2(int from,int to,int dis){
33     edge2[++num_edge2].nx=edge_head2[from];
34     edge2[num_edge2].from=from;
35     edge2[num_edge2].to=to;
36     edge2[num_edge2].dis=dis;
37     edge2[num_edge2].id=num_edge2;
38     edge_head2[from]=num_edge2;
39     return;
40 }
41 inline bool cmp(const Edge2&a,const Edge2&b){
42     if(a.dis<b.dis)return 1;
43     return 0;
44 }
45 inline int getf(int x){
46     if(fa[x]==x)return x;
47     fa[x]=getf(fa[x]);
48     return fa[x];
49 }
50 void Kruskal(){
51     sort(edge2+1,edge2+num_edge2+1,cmp);
52     for(int i=1;i<=N;i++)fa[i]=i;
53     int num=0;
54     for(int i=1;i<=num_edge2;i++){
55         int x=edge2[i].from,y=edge2[i].to;
56         int fx=getf(x),fy=getf(y);
57         if(fx!=fy){
58             num++;
59             fa[fx]=fy;
60             via[edge2[i].id]=1;
61             real_sum+=edge2[i].dis;
62             if(num==N-1)break;
63         }
64     }
65     if(num!=N-1)ans=0;
66     return;
67 }
68 inline void Dfs1(int x,int _f){
69     f[x]=_f;
70     size[x]=1;
71     dep[x]=dep[_f]+1;
72     for(int i=edge_head[x];i;i=edge[i].nx){
73         int y=edge[i].to;
74         if(y!=_f&&((((i&1)==1)&&via[(i>>1)+1])||(((i&1)==0)&&via[i>>1]))){
75             Dfs1(y,x);
76             size[x]+=size[y];
77             if(size[y]>size[son[x]])son[x]=y;
78         }
79     }
80     return;
81 }
82 inline void Dfs2(int x){
83     if(son[x]){
84         int y=son[x];
85         top[y]=top[x];
86         seg[y]=++seg[0];
87         rev[seg[0]]=y;
88         Dfs2(y);
89     }
90     for(int i=edge_head[x];i;i=edge[i].nx){
91         int y=edge[i].to;
92         if(top[y]==0&&((((i&1)==1)&&via[(i>>1)+1])||(((i&1)==0)&&via[i>>1]))){
93             top[y]=y;
94             seg[y]=++seg[0];
95             rev[seg[0]]=y;
96             Dfs2(y);
97         }
98     }
99     return;
100 }
101 struct Tree{
102     int l,r,mina,lazy;
103 }t[maxn<<3];
104 inline void Build(int x,int l,int r){
105     t[x].l=l;t[x].r=r;t[x].mina=inf;t[x].lazy=inf;
106     if(l==r)return;
107     int ls=x<<1,rs=x<<1|1,mid=(l+r)>>1;
108     Build(ls,l,mid);Build(rs,mid+1,r);
109     return;
110 }
111 inline void Pushdown(int x){
112     int ls=x<<1,rs=x<<1|1,lazy=t[x].lazy;
113     if(lazy!=inf){
114         t[ls].mina=min(t[ls].mina,lazy);t[rs].mina=min(t[rs].mina,lazy);
115         t[ls].lazy=min(t[ls].lazy,lazy);t[rs].lazy=min(t[rs].lazy,lazy);
116         t[x].lazy=inf;
117     }
118     return;
119 }
120 inline void Update(int x,int ql,int qr,int e){
121     int l=t[x].l,r=t[x].r;
122     if(ql<=l&&r<=qr){
123         t[x].mina=min(t[x].mina,e);
124         t[x].lazy=min(t[x].lazy,e);
125         return;
126     }
127     int ls=x<<1,rs=x<<1|1,mid=(l+r)>>1;
128     Pushdown(x);
129     if(ql<=mid)Update(ls,ql,qr,e);
130     if(qr>mid)Update(rs,ql,qr,e);
131     return;
132 }
133 inline void Query(int x,int q){
134     int l=t[x].l,r=t[x].r;
135     if(q==l&&l==r){
136         _ans=min(_ans,t[x].mina);
137         return;
138     }
139     int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1;
140     Pushdown(x);
141     if(q<=mid)Query(ls,q);
142     else Query(rs,q);
143     return;
144 }
145 inline void Work(int x,int y,int dis){
146     int fx=top[x],fy=top[y];
147     while(fx!=fy){
148         if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
149         Update(1,seg[fx],seg[x],dis);
150         x=f[fx];fx=top[x];
151     }
152     if(dep[x]>dep[y])swap(x,y);
153     if(x==y)return;
154     Update(1,seg[x]+1,seg[y],dis);
155     return;
156 }
157 int main(){
158     N=rd();M=rd();
159     for(int i=1;i<=M;i++){
160         x=rd();y=rd();w=rd();
161         Add_edge2(x,y,w);
162         Add_edge(x,y,w);
163         Add_edge(y,x,w);
164     }
165     Kruskal();
166     scanf("%d",&Q);
167     Dfs1(1,0);
168     seg[0]=seg[1]=rev[1]=top[1]=1;
169     Dfs2(1);
170     Build(1,1,seg[0]);
171     for(int i=1;i<=M;i++)if(via[i]==0)Work(edge[i<<1].from,edge[i<<1].to,edge[i<<1].dis);
172     while(Q--){
173         scanf("%d",&T);
174         if(ans==0){
175             puts("Not connected");
176             continue;
177         }
178         if(via[T]==0)printf("%d\n",real_sum);
179         else{
180             X=edge[T<<1].from,Y=edge[T<<1].to;_ans=inf;
181             if(dep[X]>dep[Y])Query(1,seg[X]);else Query(1,seg[Y]);
182             if(_ans==inf){
183                 puts("Not connected");
184                 continue;
185             }
186             _ans=real_sum-edge[T<<1].dis+_ans;
187             printf("%d\n",_ans);
188         }
189     }
190     return 0;
191 }

posted on 2019-02-08 21:26  AlenaNuna  阅读(187)  评论(0编辑  收藏  举报