每次加一条边 在加新边后的图中求最小生成树
先想到的就是把前i条边全部排序 但是m很大会超时
发现n很小 每次求出最小生成树时有用的边最多(n-1)条 所以每次只给n条边排序就好 求完生成树后把没用的那条边换成新边 再继续
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node
{
int u;
int v;
int w;
};
node edge[6010];
int f[210];
int n,m;
bool cmp(node n1,node n2)
{
return n1.w<n2.w;
}
int getf(int p)
{
if(f[p]==p) return p;
else
{
f[p]=getf(f[p]);
return f[p];
}
}
bool unite(int u,int v)
{
int fu,fv;
fu=getf(u);
fv=getf(v);
if(fu!=fv)
{
f[fv]=fu;
return true;
}
else return false;
}
int main()
{
int book[210];
int t,cas,i,j,sum,cnt;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
printf("Case %d:\n",cas);
for(i=1;i<=min(m,n-2);i++)
{
printf("-1\n");
}
if(m>=n-1)
{
for(i=1;i<=n;i++) f[i]=i;
sum=0,cnt=0;
for(i=1;i<=n-1;i++)
{
if(unite(edge[i].u,edge[i].v))
{
sum+=edge[i].w,cnt++;
}
}
if(cnt==n-1) printf("%d\n",sum);
else printf("-1\n");
for(i=n;i<=m;i++)
{
swap(edge[i],edge[n]);
sort(edge+1,edge+n+1,cmp);
for(j=1;j<=n;j++)
{
f[j]=j;
book[j]=0;
}
sum=0,cnt=0;
for(j=1;j<=n;j++)
{
if(unite(edge[j].u,edge[j].v))
{
book[j]=1;
sum+=edge[j].w,cnt++;
}
if(cnt==n-1) break;
}
if(cnt==n-1) printf("%d\n",sum);
else printf("-1\n");
for(j=1;j<=n;j++)
{
if(!book[j])
{
swap(edge[j],edge[n]);
break;
}
}
}
}
}
return 0;
}