CSU 1116 Kingdoms 最小生成树(prim)

由于点数只有16,而点1又必选,暴力枚举选点情况,每次做一个最小生成树

这里用的prim算法,要注意的是存在选取这些点但找不到生成树的情况,需要将之排出

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=18;
int mp[maxn][maxn];
int wi[maxn];
bool vis[maxn];
int prim(int n)
{
    int low[maxn];
    int ans=0,i,j;
    for(i=1;i<=n;i++)
        if(!vis[i])
            low[i]=mp[1][i];
        else
            low[i]=0;
    for(i=2;i<=n;i++)
    {
        int mi=INF,idx;
        for(j=2;j<=n;j++)
            if(!vis[j]&&low[j]<mi)
            {
                mi=low[j];
                idx=j;
            }
        if(mi==INF)    break;
        ans+=mi;
        vis[idx]=true;
        for(j=2;j<=n;j++)
            if(!vis[j]&&low[j]>mp[idx][j])
                low[j]=mp[idx][j];
    }
    for(i=2;i<=n;i++)
        if(!vis[i])    return INF;
    return ans;
}
int main()
{
    int i,j,n,m,k,t,u,v,w;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        memset(mp,INF,sizeof(mp));
        for(i=1;i<=n;i++)
        {
            scanf("%d",&wi[i]);
            mp[i][i]=0;
        }
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            if(mp[u][v]>w)
            mp[u][v]=mp[v][u]=w;
        }
        int len=(1<<(n-1))-1;
        int ans=0;
        for(i=0;i<=len;i++)
        {
            int x=i;
            int sum=0;
            for(j=n;j>=2;j--)
            {
                if(x&1)
                    vis[j]=true;
                else
                {
                    sum+=wi[j];
                    vis[j]=false;
                }
                x>>=1;
            }
            vis[1]=false;sum+=wi[1];
            int sk=prim(n);
            if(sk<=k&&sum>ans)    ans=sum;
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-17 03:44:43

CSU 1116 Kingdoms 最小生成树(prim)的相关文章

CSU 1116 Kingdoms(枚举最小生成树)

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1116 解题报告:一个国家有n个城市,有m条路可以修,修每条路要一定的金币,现在这个国家只有K个金币,每个城市有一些人,要你求怎么修路使得总的费用在K的范围内,同时使得跟首都连接的城市的人口(包括首都的人口)要最多,问最多的人口是多少. 枚举连接哪些城市,然后分别构造最小生成树. 1 #include<cstdio> 2 #include<cstring> 3 #inclu

CSU 1116 Kingdoms

传送门 Description A kingdom has n cities numbered 1 to n, and some bidirectional roads connecting cities. The capital is always city 1. After a war, all the roads of the kingdom are destroyed. The king wants to rebuild some of the roads to connect the

csuoj 1116: Kingdoms

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1116 1116: Kingdoms Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 293  Solved: 82[Submit][Status][Web Board] Description A kingdom has n cities numbered 1 to n, and some bidirectional roads connecting

poj1861 最小生成树 prim &amp; kruskal

// poj1861 最小生成树 prim & kruskal // // 一个水题,为的只是回味一下模板,日后好有个照应不是 #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <iostream> using namespace std; const int MAX_N = 1008; const int INF =

nyist oj 38 布线问题 (最小生成树 prim)

布线问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一种布线方式,该布线方式需要满足以下条件: 1.把所有的楼都供上电. 2.所用电线花费最少 输入 第一行是一个整数n表示有n组测试数据.(n<5) 每组测试数据的第一行是两个整数v,e. v表示学校里楼的总个数(v<=500) 随后的e行里,每行有三个整数a,b,c表示a与b之间如果建铺设线路花费为c(c<=100).(哪两栋楼间如果没有指明花费

最小生成树--prim算法

一个无向图G的最小生成树就是由该图的那些连接G的所有顶点的边构成的树,且其总价值最低,因此,最小生成树存在的充分必要条件为图G是连通的,简单点说如下: 1.树的定义:有n个顶点和n-1条边,没有回路的称为树 生成树的定义:生成树就是包含全部顶点,n-1(n为顶点数)条边都在图里就是生成树 最小:指的是这些边加起来的权重之和最小 2.判定条件:向生成树中任加一条边都一定构成回路 充分必要条件:最小生成树存在那么图一定是连通的,反过来,图是连通的则最小生成树一定存在 上图的红色的边加上顶点就是原图的

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

题目链接: csu 1116 题意: 有一幅双向图连接N个城市(标号1~n,1表示首都)  每个城市有一个价值W. 地震摧毁了所有道路,现给出可修复的m条道路并给出修复每条道路所需的费用 问在总费用不超过k的情况下,使得  与  首都连通的所有城市  的价值和 最大 解题思路: 点的数量不超过16 ,2^16次方枚举所有城市是否在连通的集合类 再通过kruskal判断这个集合是否合法即可 代码: #include<iostream> #include<cstdio> #includ

hdu 3371 最小生成树prim算法

Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8992    Accepted Submission(s): 2519 Problem Description In 2100, since the sea level rise, most of the cities disappear. Thoug

最小生成树Prim

首先解释什么是最小生成树,最小生成树是指在一张图中找出一棵树,任意两点的距离已经是最短的了. 算法要点: 1.用book数组存放访问过的节点. 2.用dis数组保存对应下标的点到树的最近距离,这里要注意,是对树最近的距离,而不是源点,这和单源最短路径是有区别的. 3.用maps数组保存边的关系. 4.每次先找到离树最近的且没有被访问过的点,以这点的所有边去更新dis数组,也就是更新和树的最近距离. 算法模型: for(循环n-1次,因为默认1点为起始点,已经被访问了) { for(循环n次.)