【数据规模】
对于20%的数据, n≤1000,m≤6000,Q≤6000。
有20%的数据,n≤1000,m≤50000,Q≤8000,修改后的代价不会比之前的代价低。
对于100%的数据, n≤20000,m≤50000,Q≤50000。
Day2
高端洋气上档次的动态最小生成树。。。
想当年听7k+在WC上侃侃而谈时SB的听不懂。。。。
好吧。。。
总而言之有2个操作
Contraction & Reduction
这个我也不废话了。。。
但是这题需要重构边图。。。一开始看到想吐血。。
后来发现边的存储形式是(x,y,w) 和不是邻接表 这样就随便了。。。(喂)
细节是硬伤。。。。
// 动态最小生成树--很麻烦的题目。。。先理解再说吧,,, // 考场出这种题目是什么心态。。。。。。、 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<cctype> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define F (100000007) #define MAXN (20000+10) #define MAXM (50000+10) #define MAXQ (50000+10) #define MAXZi (50000000) #define INF (50000000+1) #define inf (-1) long long mul(long long a,long long b){return (a*b)%F;} long long add(long long a,long long b){return (a+b)%F;} long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;} typedef long long ll; int n,m,q; /* struct E { int edge[MAXM],next[MAXM],pre[MAXN],size; ll weight[MAXM]; E(){edge[MAXN]=next[MAXN]=(0);size=0;} void addedge(int u,int v,ll w) { edge[++size]=v; weight[size]=w; next[size]=pre[u]; pre[u]=size; } void addedge2(int u,int v,ll w){addedge(u,v,w),addedge(v,u,w); } }e,e2;*/ struct E { int x,y; ll w; }e[MAXM*30],*e_tail=e; struct comm { int num; ll val; }ask[MAXQ],back[MAXQ*30],*back_tail=back; ll ans[MAXQ]={0}; struct unionset { int father[MAXN]; void init(int n){For(i,n) father[i]=i; } int getfather(int x) { if (father[x]==x) return x; return father[x]=getfather(father[x]); } bool union2(int x,int y) { if (getfather(x)==getfather(y)) return 0; father[getfather(x)]=getfather(y);return 1; } }ufs; int eidx[MAXM*10],newV[MAXN],newE[MAXM]; bool cmp(int i,int j){return e_tail[i].w<e_tail[j].w;} void solve(int n,E *_e,int m,int l,int r,ll inherent) //e_tail表示上次e的结尾 { e_tail+=m; E *e=e_tail; copy(_e,e_tail,e); if (l==r) { e[ask[l].num].w=ask[l].val; ufs.init(n); Rep(i,m) eidx[i]=i;sort(eidx,eidx+m,cmp); Rep(i,m) { int id=eidx[i]; if (ufs.union2(e[id].x,e[id].y)) inherent+=e[id].w; } ans[l]=inherent; e_tail-=m; return; } // Con-must edge static bool b[MAXM]={0}; memset(b,0,sizeof(b)); Fork(i,l,r) e[ask[i].num].w=inf; ufs.init(n); Rep(i,m) eidx[i]=i;sort(eidx,eidx+m,cmp); Rep(i,m) { int id=eidx[i]; if (ufs.union2(e[id].x,e[id].y)&&e[id].w!=inf) inherent+=e[id].w,b[id]=1; } ufs.init(n);Rep(i,m) if (b[i]) ufs.union2(e[i].x,e[i].y); //改动边不缩点 int n2=0; For(i,n) if (ufs.getfather(i)==i) newV[i]=++n2; For(i,n) if (ufs.getfather(i)^i) newV[i]=newV[ufs.getfather(i)]; Rep(i,m) e[i].x=newV[e[i].x],e[i].y=newV[e[i].y]; // Red-impossible edge Fork(i,l,r) e[ask[i].num].w=INF; ufs.init(n2); Rep(i,m) eidx[i]=i;sort(eidx,eidx+m,cmp); Rep(i,m) { int id=eidx[i]; if (ufs.union2(e[id].x,e[id].y)||e[id].w==INF) b[id]=1;else b[id]=0; }//若 x=y 则b[i]=0 保证不出先当前修改边 int m2=0; //边从0标号 m2比实际值大1(Rep) Rep(i,m) if (b[i]) newE[i]=m2++; Fork(i,l,r) e[ask[i].num].w=_e[ask[i].num].w,ask[i].num=newE[ask[i].num]; Rep(i,m) if (b[i]) e[newE[i]]=e[i]; { int m=l+r>>1,len=m-l+1; comm *back_head=back_tail; back_tail+=len; copy(ask+l,ask+m+1,back_head); if (l<=m) solve(n2,e,m2,l,m,inherent); copy(back_head,back_head+len,ask+l); back_tail-=len; Fork(i,l,m) e[ask[i].num].w=ask[i].val; if (m<r) solve(n2,e,m2,m+1,r,inherent); } e_tail-=m; } int main() { // freopen("bzoj2001.in","r",stdin); scanf("%d%d%d",&n,&m,&q); Rep(i,m) //保证备份的紧凑性 { scanf("%d%d%lld",&e[i].x,&e[i].y,&e[i].w); } Rep(i,q) { scanf("%d%lld",&ask[i].num,&ask[i].val);ask[i].num--; } solve(n,e,m,0,q-1,0); Rep(i,q) printf("%lld\n",ans[i]); return 0; }