***LightOJ 1123 Trail Maintenance(kruskal+环内删除权值最大边)

上不能屠犇,下不能虐渣,排位赛一直被吊打。

这题是个kruskal,但是他是每次新给你一条边,然后加进去求MST的权值和,等到成为MST后,每次新加入一条边,都会形成一个环,然后需要去除环内最大的边,so这点是关键,如果次次都用kruskal显然是承受不起的。

#include<iostream>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<stack>

using namespace std;
#define MAX 100000+5
#define MAXN 100000+5
typedef long long LL;

const double pi=3.141592653589793;
const int INF=1e9;
const double inf=1e20;
const double eps=1e-10;
const int mod=1000000007;

struct E{
    int u,v,de;
}e[50000];

int pre[205];
int vis[205][205];
int cnt,n,w;

int Find(int x){
    return pre[x]==x?x:pre[x]=Find(pre[x]);
}

void Union(int x,int y){
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy) pre[fx]=fy;
}

bool cmp(struct E a,struct E b){
    return a.de<b.de;
}

int  kruskal(){
    for(int i=1;i<=n;i++) pre[i]=i;
    int tmp=0;
    int conn=0;
    int ans=0;
    for(int i=0;i<cnt;i++){
        int a=Find(e[i].u);
        int b=Find(e[i].v);
        if(a==b){
            tmp=i;
            continue;
        }
        conn++;
        pre[a]=b;
        ans+=e[i].de;
    }
    if(tmp!=0) e[tmp]=e[--cnt];
    if(conn!=n-1) return -1;
    return ans;
}
int main(){
    int t,kase=0;
    cin>>t;
    while(t--){
        kase++;
        scanf("%d%d",&n,&w);
        cnt=0;
        printf("Case %d:\n",kase);
        for(int i=0;i<w;i++){
            scanf("%d%d%d",&e[cnt].u,&e[cnt].v,&e[cnt].de);
            cnt++;
            sort(e,e+cnt,cmp);
            printf("%d\n",kruskal());
        }
    }
    return 0;
}


你可能感兴趣的:(ACM,kruskal,lightoj)