• csu1116 Kingdoms 最小生成树-枚举状态


    题目链接:

    csu 1116




    题意:

    有一幅双向图连接N个城市(标号1~n,1表示首都)  每一个城市有一个价值W.

    地震摧毁了全部道路,现给出可修复的m条道路并给出修复每条道路所需的费用

    问在总费用不超过k的情况下,使得  与  首都连通的全部城市  的价值和 最大



    解题思路:

    点的数量不超过16 ,2^16次方枚举全部城市是否在连通的集合类

    再通过kruskal推断这个集合是否合法就可以




    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct node{
        int a,b,w;
    }edge[128];
    int v[18];
    int fa[18];
    int sum;
    
    void init()
    {
        for(int i=0;i<18;i++)
            fa[i]=i;
        sum=0;
    }
    
    int Find(int x)
    {
        return x==fa[x]?x:fa[x]=Find(fa[x]);
    }
    
    int cmp(node a,node b)
    {
        return a.w<b.w;
    }
    
    int main()
    {
        int T,n,m,k;
        int ans;
        int f1,f2;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&k);
            ans=0;
            for(int i=1;i<=n;i++)
                scanf("%d",&v[i]);
            for(int i=0;i<m;i++)
                scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].w);
            sort(edge,edge+m,cmp);                                  //给边排序 保证费用尽量小
            int num=(1<<n)-1;
            for(int i=0;i<=num;i++)
            {
                if(i&1)
                {
                    init();
                    for(int j=0;j<m;j++)
                        if(i&(1<<edge[j].a-1))
                            if(i&(1<<edge[j].b-1))              //当前边属于当前的点集
                            {
                                f1=Find(edge[j].a);
                                f2=Find(edge[j].b);
                                if(f1!=f2)
                                {
                                    fa[f1]=f2;
                                    sum+=edge[j].w;
                                }
                            }
                    for(int j=1;j<=n;j++)
                        if((i&(1<<j-1))&&Find(j)!=Find(1))        //当前点集有多余的点
                        {
                            sum=k+1;
                            break;
                        }
                    if(sum<=k)
                    {
                        sum=0;
                        for(int j=1;j<=n;j++)
                            if(i&(1<<j-1))
                                sum+=v[j];
                        if(sum>ans)
                            ans=sum;
                    }
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    


  • 相关阅读:
    Golang sync.map 设计思想和底层源码分析
    【LeetCode】验证二叉搜索树(dfs或中序遍历)
    逆序对板子
    the expound of tire or the interpret of tire or the explicate of tire or the explain of tire(no face)
    hash(1):关于坐标hash:unordered_set 和 hash表
    图的联通
    哈哈哈
    nlog(n)求lcs
    大数据教程01HDFS的基本组成和原理
    [转][MongoDB]安装设置
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/6838302.html
Copyright © 2020-2023  润新知