P1340 兽径管理 (最小生成树)

题目链接

 题解:

先用所有的边生成一棵最小生成树,然后从后往前不断删边,看此边有没有用到,用到的话重新跑生成树,没有的话结果不变。还是Kruskal方便些。。。

Prime:

#include <bits/stdc++.h>
# define LL long long
using namespace std;

const int INF=0x7fffffff;
int N,W;
int dis[220];
int complete[220];
int used[6010];
int pre[220];
int removed;
struct Edge{
    int next;
    int to;
    int l;
    int id;
}e[6010<<1];
int head[220];
int en;

void add(int from, int to, int w, int id){
    e[en].next=head[from];
    e[en].to=to;
    e[en].l=w;
    e[en].id=id;
    head[from]=en;
    ++en;
}

int findmin(){
    int mi=INF;
    int id=0;
    for(int i=1;i<=N;++i){
        if(complete[i]==1) continue;
        if(dis[i]<mi){
            mi=dis[i];
            id=i;
        }
    }
    return id;
}

int prime(){
    for(int i=1;i<=N;++i){
        dis[i]=INF;
    }
    memset(complete,0,sizeof(complete));
    memset(pre,-1,sizeof(pre));
    memset(used,0,sizeof(used));
    dis[1]=0;
    for(int i=1;i<=N-1;++i){
        int u=findmin();
        if(u==0) break;
        complete[u]=1;
        for(int j=head[u];j!=-1;j=e[j].next){
            int v=e[j].to;
            int ei=e[j].id;
            if(ei>removed) continue;
            if(complete[v]==0 && e[j].l<dis[v]){
                dis[v]=e[j].l;
                pre[v]=e[j].id;
            }
        }
    }
    int res=0;
    for(int i=1;i<=N;++i){
        if(dis[i]==INF) return -1;
        res+=dis[i];
        if(i>1){
            used[pre[i]]=1;
        }
    }
    return res;
}

int main(){
    memset(head,-1,sizeof(head));
    scanf("%d %d", &N, &W);
    for(int i=1;i<=W;++i){
        int u,v,w;
        scanf("%d %d %d", &u, &v, &w);
        add(u,v,w,i);
        add(v,u,w,i);
    }
    vector<int> res(W+1);
    removed=W;
    int t=prime();
    if(t==-1){
        for(int i=1;i<=W;++i){
            printf("-1
");
        }
        return 0;
    }
    res[W]=t;

    for(int i=W-1;i>=1;--i){
        removed=i; //大于removed的都删掉了
        if(used[i+1]==1){

            t=prime();
            if(t==-1){
                for(int j=i;j>=1;--j){
                    res[j]=-1;
                }
                break;
            }
            res[i]=t;
        }else{
            res[i]=res[i+1];
        }
    }
    for(int i=1;i<=W;++i){
        printf("%d
", res[i]);
    }
    return 0;
}

Kruskal:

#include <bits/stdc++.h>
# define LL long long
using namespace std;

const int INF=0x7fffffff;
int N,W;
int used[6010];
int removed[6010];
int parent[210];
struct Edge{
    int from;
    int to;
    int l;
    int id;

    bool operator< (Edge e1){
        return l<e1.l;
    }
}e[6010];
int en;

void add(int from, int to, int w, int id){
    e[en].from=from;
    e[en].to=to;
    e[en].l=w;
    e[en].id=id;
    ++en;
}

int find(int p){
    if(p==parent[p]) return p;

    parent[p]=find(parent[p]);
    return parent[p];
}

int Kruskal(){
    memset(used,0,sizeof(used));
    for(int i=1;i<=N;++i) parent[i]=i;
    int sum=0;
    int cnt=0;
    for(int i=1;i<=W;++i){
        int id=e[i].id;
        if(removed[id]==1) continue;
        int u=e[i].from;
        int v=e[i].to;
        int w=e[i].l;

        int fu=find(u);
        int fv=find(v);
        if(fu==fv) continue;

        cnt++;
        sum+=w;
        used[id]=1;
        parent[fu]=fv;
        if(cnt==N-1) return sum;
    }
    return -1;
}

int main(){
    scanf("%d %d", &N, &W);
    en=1;
    for(int i=1;i<=W;++i){
        int u,v,w;
        scanf("%d %d %d", &u, &v, &w);
        add(u,v,w,i);
    }
    sort(e+1,e+W+1);
    vector<int> res(W+1);
    int t=Kruskal();

    if(t==-1){
        for(int i=1;i<=W;++i){
            printf("-1
");
        }
        return 0;
    }
    res[W]=t;

    for(int i=W-1;i>=1;--i){
        removed[i+1]=1;
        if(used[i+1]==1){
            t=Kruskal();
            if(t==-1){
                for(int j=i;j>=1;--j){
                    res[j]=-1;
                }
                break;
            }
            res[i]=t;
        }else{
            res[i]=res[i+1];
        }
    }
    for(int i=1;i<=W;++i){
        printf("%d
", res[i]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/FEIIEF/p/12268244.html