n个点 m条边 后面会有q个操作 每次操作添加一条边 每次操作之后输出当前最小生成树边的权值和
对于前m条边 建边 求出最小生成树 由于q的值蛮大 如果每次都是直接插入再用kruskal求最小生成树
一定会tle 所以我们保留之间最小生成树的边
因为 添加一条新的边 在最小生成树中可能会形成一个环 所以我们用dfs求出这段环中边的权值最大的边
如果这边的权值大于插入的边的权值 所以需要把这条边删除(这里用到了vector erase操作 我也是第一次使用)
然后保留插入的这条边
在此感谢glq当时敲出了这道题
<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 10010
#define MAXM 101010
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)
using namespace std;
int Read()
{
char ch;
int a = 0;
while((ch = getchar()) == ' ' | ch == '\n');
a += ch - '0';
while((ch = getchar()) != ' ' && ch != '\n')
{
a *= 10;
a += ch - '0';
}
return a;
}
void Print(int a)
{
if(a>9)
Print(a/10);
putchar(a%10+'0');
}
int F[MAXN];
struct Edge
{
int u,v,w;
}edge[MAXM];
int flag[MAXM];
int tol;
vector<pair<int,int> > vec[MAXN];
vector<pair<int,int> >::iterator it;
void addedge(int u,int v,int w)
{
edge[tol].u=u;
edge[tol].v=v;
edge[tol++].w=w;
}
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int find(int x)
{
if(F[x]==-1) return x;
return F[x]=find(F[x]);
}
int Kruskal(int n)
{
MEM(F,-1);
MEM(flag,0);
sort(edge,edge+tol,cmp);
int cnt=0;
int ans=0;
for(int i=0;i<tol;i++)
{
int u=edge[i].u;
int v=edge[i].v;
int w=edge[i].w;
int t1=find(u);
int t2=find(v);
if(t1!=t2)
{
ans+=w;
F[t1]=t2;
cnt++;
flag[i]=1;
}
if(cnt==n-1) break;
}
if(cnt<n-1) return -1;
return ans;
}
int cir[MAXN][3];
void dfs(int x,int y)
{
// bug;
int sz=vec[x].size();
for(int i=0;i<sz;i++)
if(vec[x][i].first!=y)
{
int v=vec[x][i].first,w=vec[x][i].second;
if(cir[x][0]<w)
{
cir[v][0]=w; cir[v][1]=x; cir[v][2]=v;
}
else
{
cir[v][0]=cir[x][0]; cir[v][1]=cir[x][1]; cir[v][2]=cir[x][2];
}
dfs(v,x);
}
}
int main()
{
// fread;
int n,m,q;
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
tol=0;
for(int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
// addedge(v,u,w);
}
for(int i=0;i<=n;i++)
vec[i].clear();
int ans=Kruskal(n);
for(int i=0;i<m;i++)
{
if(flag[i])
{
vec[edge[i].u].push_back(make_pair(edge[i].v,edge[i].w));
vec[edge[i].v].push_back(make_pair(edge[i].u,edge[i].w));
}
}
for(int i=0;i<q;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
for(int j=0;j<=n;j++)
cir[j][0]=0;
dfs(u,u);//遍历u v之间的那些边 因为可能会形成一个环找出这个环中边的权值最大那个
if(cir[v][0]>w)
{
ans=ans-cir[v][0]+w;
int x=cir[v][1],y=cir[v][2];
for(it=vec[x].begin();it!=vec[x].end();it++)
{
if(it->first==y)
{
vec[x].erase(it); break;
}
}
for(it=vec[y].begin();it!=vec[y].end();it++)
{
if(it->first==x)
{
vec[y].erase(it); break;
}
}
vec[u].push_back(make_pair(v,w));
vec[v].push_back(make_pair(u,w));
}
printf("%d\n",ans);
}
}
return 0;
}
</span>