zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Android View 阴影的总结
    清晰的教你如何将 Maven 项目上传至 中央仓库以及版本更新
    简单粗暴的上传项目至 Github
    App自动更新(DownloadManager下载器)
    类型判断
    前端防御XSS
    window.location.href/replace/reload()/页面跳转+替换+刷新
    对数组排序进行"洗牌"(随机排序)
    iframe跨域上传图片
    Vim 新手节省时间的小技巧
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12268244.html
Copyright © 2011-2022 走看看