p1195口袋里的云(java实现)

题目背景 小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空。 有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖。
给你云朵的个数N,再给你M个关系,表示哪些云朵可以连在一起。
现在小杉要把所有云朵连成K个棉花糖,一个棉花糖最少要用掉一朵云,小杉想知道他怎么连,花费的代价最小。

本题通过代价最小可以锁定是最小生成树的题目,首选并查集,kurscal算法。
本题关键在于审题,实现并没有难度,一开始老是挂,一开始的思路是,题目种说一个棉花糖最少要用掉一朵云,那么我每次连上一条边就能有2个棉花糖,直接用并查集加边,但是一直是错的,只过了一个点,我反复检查了代码并没有发现错误,因此,只可能是题目看错了。我在想为什么要给n个点,只要有k个点就可以了,后来转念一想,他说的k个棉花糖的意思是要用n个点组成k个生成树。审题非常关键,有时候代码并不难写,反而是题目都读不清楚,造成错误。
k个生成树,可以用推断法:kruscal算法生成一棵最小生成树,需要n-1条边,那么2棵树就需要n-2条边,k棵树就要n-k条边,只要我们能找到n-k条边就完成了题目要求。

public class Main {
    static List<edge> edges = new ArrayList<edge>();
    static int m,n,k;
    static int[] id;
    public static void main(String[] args) throws Exception{
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String[] sa = reader.readLine().split(" ");
        n=Integer.parseInt(sa[0]);
        m=Integer.parseInt(sa[1]);
        k=Integer.parseInt(sa[2]);
        for(int i=0;i<m;i++){
            String[] sb = reader.readLine().split(" ");
            edges.add(new edge(Integer.parseInt(sb[0]),Integer.parseInt(sb[1]),Integer.parseInt(sb[2])));
        }
        Collections.sort(edges);
        init();
        int res =0;
        int cost=0;
        for(edge edge:edges){
            if(find(edge.u)!=find(edge.v)){
                cost++;
                union(edge.u,edge.v);
                res+=edge.w;
                if(cost==n-k) break;
            }
        }
        if(cost<n-k) System.out.println("No Answer");
        else System.out.println(res);

    }
    //接下来三个函数实现并查集
    public static void init(){
        id = new int[n+1];
        for(int i=1;i<=n;i++) id[i] = i;
    }
    public static int find(int x){
        while(x!=id[x]) x = id[id[x]];
        return x;
    }
    public static void union(int x,int y){
        x = find(x);
        y = find(y);
        if(x==y) return;
        id[y] = x;
    }
    //保存边的信息
    static class edge implements Comparable<edge> {
        int u,v,w;
        public edge(int u,int v,int w){
            this.u = u;
            this.v = v;
            this.w = w;
        }

        @Override
        public int compareTo(edge o) {
            if(this.w > o.w) return 1;
            if(this.w == o.w) return 0;
            else return -1;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值