[动态最小生成树 CDQ分治 Kruscal] BZOJ 2001 [Hnoi2010]City 城市建设

来源:互联网 发布:最优化理论与应用 编辑:程序博客网 时间:2024/06/05 05:05

思路不难想 借鉴了其他人的代码:http://blog.sina.com.cn/s/blog_6e63f59e0101blum.html

两个关键的操作:
Reduction(删除无用边):
把待修改的边标为INF,做一遍MST,把做完后不在MST中的非INF边删去(因为这些边在原图的情况下肯定更不可能选进MST的边集,即无用边);
Contraction(缩必须边,缩点):
把待修改的边标为-INF,做一遍MST,在MST中的非-INF边为必须边(因为这些边在原图的情况下也一定会被选进MST),缩点。

#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef pair<int,int> abcd;typedef long long ll;inline char nc(){static char buf[100000],*p1=buf,*p2=buf;if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }return *p1++;}inline void read(int &x){char c=nc(),b=1;for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int oo=1<<30;const int N=50005;int n,m;struct edge{int u,v,w,pos;bool operator < (const edge &B) const{return w<B.w;}}e[25][N],d[N],t[N];int c[N];int a[N];int fat[N],rank[N];inline void init(edge *d,int n){for (int i=1;i<=n;i++)fat[d[i].u]=d[i].u,fat[d[i].v]=d[i].v,rank[d[i].u]=rank[d[i].v]=0;}inline int Fat(int u){return u==fat[u]?u:fat[u]=Fat(fat[u]);}inline bool Union(int x,int y){x=Fat(x),y=Fat(y); if (x==y) return 0;if (rank[x]>rank[y]) swap(x,y);if (rank[x]==rank[y]) rank[y]++;fat[x]=y; return 1;}abcd q[N]; int Q;ll ans[N];inline ll contraction(int &eds){int tmp=0; ll tsum=0;init(d,eds);sort(d+1,d+eds+1);for (int i=1;i<=eds;i++)if (Union(d[i].u,d[i].v))t[++tmp]=d[i];init(d,eds);for (int i=1;i<=tmp;i++)if (t[i].w!=-oo && Union(t[i].u,t[i].v))tsum+=t[i].w;tmp=0;for (int i=1;i<=eds;i++)if (Fat(d[i].u)!=Fat(d[i].v)){t[++tmp]=d[i];t[tmp].u=Fat(t[tmp].u);t[tmp].v=Fat(t[tmp].v);c[t[tmp].pos]=tmp;}for (int i=1;i<=tmp;i++) d[i]=t[i]; eds=tmp;return tsum;}inline void reduce(int &eds){int tmp=0;init(d,eds);sort(d+1,d+eds+1);for (int i=1;i<=eds;i++)if (Union(d[i].u,d[i].v) || d[i].w==oo){t[++tmp]=d[i];c[t[tmp].pos]=tmp;}for (int i=1;i<=tmp;i++) d[i]=t[i]; eds=tmp;}void Solve(int l,int r,int cur,int eds,ll sum){if (l==r) a[q[l].first]=q[l].second;for (int i=1;i<=eds;i++) e[cur][i].w=a[e[cur][i].pos],d[i]=e[cur][i],c[d[i].pos]=i;if (l==r){ans[l]=sum;init(d,eds);sort(d+1,d+eds+1);for (int i=1;i<=eds;i++)if (Union(d[i].u,d[i].v))ans[l]+=d[i].w;return;}for (int i=l;i<=r;i++) d[c[q[i].first]].w=-oo;sum+=contraction(eds);for (int i=l;i<=r;i++) d[c[q[i].first]].w=oo;reduce(eds);for (int i=1;i<=eds;i++) e[cur+1][i]=d[i];int mid=(l+r)>>1;Solve(l,mid,cur+1,eds,sum);Solve(mid+1,r,cur+1,eds,sum);}int main(){freopen("t.in","r",stdin);freopen("t.out","w",stdout);read(n); read(m); read(Q);for (int i=1;i<=m;i++)read(e[0][i].u),read(e[0][i].v),read(e[0][i].w),a[i]=e[0][i].w,e[0][i].pos=i;for (int i=1;i<=Q;i++)read(q[i].first),read(q[i].second);Solve(1,Q,0,m,0);for (int i=1;i<=Q;i++)printf("%lld\n",ans[i]);return 0;}


0 0