题目详情
题目解析
动态最小生成树用线段树维护,线段树维护的区间的是所有的边,线段树的点维护一个数组,代表这一段边的区间组成的最小生成树用到了哪些边的编号,合并的过程类似归并排序,在两段的最小生成树边中挑,构造出新的最小生成树,记录所使用的边
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=210,M=30010;
struct Edge
{
int a,b,c;
}e[M];
struct Node
{
int id[N];
}tr[M*8];
int p[N];
int ans[N],tmp[N];
int n,m,q;
int find(int x)
{
if(x!=p[x])return find(p[x]);
return p[x];
}
void pushup(int root)
{
for(int i=1;i<=n;i++)p[i]=i,tr[root].id[i]=0;
int l=root*2,r=root*2+1;
int pp=1,qq=1;
for(int i=1;i<n;)
{
int pos1=tr[l].id[pp],pos2=tr[r].id[qq];
if(!pos1&&!pos2)break;
if(!pos1||(pos2&&e[pos1].c>=e[pos2].c))
{
int a=find(e[pos2].a);
int b=find(e[pos2].b);
if(a!=b)
{
tr[root].id[i]=pos2;
p[a]=b;
i++;
}
qq++;
}
else
{
int a=find(e[pos1].a);
int b=find(e[pos1].b);
if(a!=b)
{
tr[root].id[i]=pos1;
p[a]=b;
i++;
}
pp++;
}
}
}
void build(int u,int l,int r)
{
if(l==r)
{
tr[u].id[1]=l;
return ;
}
int mid=l+r>>1;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
pushup(u);
}
void update(int u,int l,int r,int x)
{
if(l==r)return;
int mid=l+r>>1;
if(x<=mid)update(u*2,l,mid,x);
else update(u*2+1,mid+1,r,x);
pushup(u);
}
void solve(int root)
{
for(int i=1;i<=n;i++)p[i]=i,tmp[i]=0;
int pp=1,qq=1;
for(int i=1;i<n;)
{
int pos1=tr[root].id[pp];
int pos2=ans[qq];
if(!pos1&&!pos2)break;
if(!pos1||(pos2&&e[pos1].c>=e[pos2].c))
{
int a=find(e[pos2].a);
int b=find(e[pos2].b);
if(a!=b)
{
tmp[i]=pos2;
p[a]=b;
i++;
}
qq++;
}
else
{
int a=find(e[pos1].a);
int b=find(e[pos1].b);
if(a!=b)
{
tmp[i]=pos1;
p[a]=b;
i++;
}
pp++;
}
}
for(int i=1;i<=n;i++)ans[i]=tmp[i];
}
void query(int u,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
{
solve(u);
return ;
}
int mid=l+r>>1;
if(L<=mid)query(u*2,l,mid,L,R);
if(R>mid)query(u*2+1,mid+1,r,L,R);
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
}
build(1,1,m);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x,y,z,t;
scanf("%d%d%d%d",&x,&y,&z,&t);
e[x].a=y,e[x].b=z,e[x].c=t;
update(1,1,m,x);
}
else
{
memset(ans,0,sizeof(ans));
int l,r;
scanf("%d%d",&l,&r);
query(1,1,m,l,r);
if(!ans[n-1])puts("Impossible");
else
{
ll res=0;
for(int i=1;i<=n;i++)res+=e[ans[i]].c;
cout<<res<<endl;
}
}
}
return 0;
}