hdu之Ice_cream's world(hdu 2120、2121、2122)

hdu之Ice_cream’s world(hdu 2120、2121、2122)

一、Ice_cream’s world I hdu 2120


Problem Description


ice_cream’s world is a rich country, it has many fertile lands. Today, the queen of ice_cream wants award land to diligent ACMers. So there are some watchtowers are set up, and wall between watchtowers be build, in order to partition the ice_cream’s world. But how many ACMers at most can be awarded by the queen is a big problem. One wall-surrounded land must be given to only one ACMer and no walls are crossed, if you can help the queen solve this problem, you will be get a land.


Input


In the case, first two integers N, M (N<=1000, M<=10000) is represent the number of watchtower and the number of wall. The watchtower numbered from 0 to N-1. Next following M lines, every line contain two integers A, B mean between A and B has a wall(A and B are distinct). Terminate by end of file.


Output


Output the maximum number of ACMers who will be awarded.
One answer one line.


Sample Input


8 10
0 1
1 2
1 3
2 4
3 4
0 5
5 6
6 7
3 6
4 7


Sample Output


3

题解:题意就是:判断无向图有几个环,一道并查集水题,居然开始没做出来。。。。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int par[1010];       //存放父亲数组
int n,m;             //n表示结点个数、m表示边条数

/**路径压缩查找父亲节点*/
int get_par(int a)
{
    if(par[a]!=a)
        par[a]=get_par(par[a]);
    return par[a];
}
/**判断的同时,如果父节点不相同则合并*/
int Merge(int a,int b)
{
    int par_a=get_par(a);
    int par_b=get_par(b);
    if(par_a!=par_b)
    {
        par[par_a]=par_b;
        return 0;
    }
    return 1;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {

        /**父亲数组初始化*/
        for(int i=0; i<n; i++)
            par[i]=i;

        int a,b;
        int sum=0;
        for(int i=0; i<m; i++)
        {
            scanf("%d%d",&a,&b);
            sum+=Merge(a,b);
        }
        printf("%d\n",sum);
    }
    return 0;
}

二、Ice_cream’s world II hdu 2121


Problem Description


After awarded lands to ACMers, the queen want to choose a city be her capital. This is an important event in ice_cream world, and it also a very difficult problem, because the world have N cities and M roads, every road was directed. Wiskey is a chief engineer in ice_cream world. The queen asked Wiskey must find a suitable location to establish the capital, beautify the roads which let capital can visit each city and the project’s cost as less as better. If Wiskey can’t fulfill the queen’s require, he will be punishing.


Input


Every case have two integers N and M (N<=1000, M<=10000), the cities numbered 0…N-1, following M lines, each line contain three integers S, T and C, meaning from S to T have a road will cost C.


Output


If no location satisfy the queen’s require, you must be output “impossible”, otherwise, print the minimum cost in this project and suitable city’s number. May be exist many suitable cities, choose the minimum number city. After every case print one blank.


Sample Input


3 1
0 1 1

4 4
0 1 10
0 2 10
1 3 20
2 3 30


Sample Output


impossible

40 0

题解:一道不定根求有向图最小生成树的题,当开始直接准备一顿猛操作,用每个结点依次创建最小生成树,然后进行比较,很明显TLE

于是参考了下面大佬的博客:

https://blog.csdn.net/lianai911/article/details/42277235

思路:求有向图的最小树形图,不过根节点是不定的。虚拟一个根结点,到每个

结点都有一条边,其到每个结点的权值应该相等,表明每个结点都应该且都有机

会当根。且边的权值应比总权值大一些。如果最终算出的最小树形图的总权值大

于或等于 原图的总权值 + 虚根到实根(也就是原图的总权值),其实就是算出的最

小树形图的总权值大于或等于 原图总权值的二倍,就不能构成有向图的最小树形

图。

代码的话,看大佬的吧,我实在没搞太懂。。。。(wuwuwu)

三、Ice_cream’s world III


Problem Description


ice_cream’s world becomes stronger and stronger; every road is built as undirected. The queen enjoys traveling around her world; the queen’s requirement is like II problem, beautifies the roads, by which there are some ways from every city to the capital. The project’s cost should be as less as better.


Input


Every case have two integers N and M (N<=1000, M<=10000) meaning N cities and M roads, the cities numbered 0…N-1, following N lines, each line contain three integers S, T and C, meaning S connected with T have a road will cost C.


Output


If Wiskey can’t satisfy the queen’s requirement, you must be output “impossible”, otherwise, print the minimum cost in this project. After every case print one blank.


Sample Input


2 1
0 1 10

4 0


Sample Output


10

impossible

题意:基本上看懂后就发现,一道求无向图最小生成树的水题,在这显然用Prim算法较好(因为结点个数远小于边的条数)

至于Prim算法,这里有我另外一篇博客:

最小生成树概念及其构建(Prim算法、Kruskal算法)

于是代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Max 999999     //设置一个最大值
using namespace std;
int n,m;             //n表示结点个数、m表示边的条数
int vis[1010];       //判断结点是否访问
int mp[1010][1010];  //无向图邻接矩阵
int cost[1010];      //最小生成树每条边权值

/**初始化邻接矩阵*/
void init()
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(i==j)
                mp[i][j]=0;
            else
                mp[i][j]=Max;
        }
    }
}

/**Prim算法*/
void Prim()
{/**以顶点0为出发点*/

    //memset(vis,0,sizeof(vis));      //放在这会Runtime Error。。。

    for(int i=1;i<n;i++)
    {
        cost[i]=mp[0][i];
    }
    cost[0]=0;
    vis[0]=1;
    for(int i=0;i<n;i++)
    {
        int Min=Max+1;
        int pos;
        for(int j=0;j<n;j++)
        {
            if(cost[j]<Min&&vis[j]==0)
            {
                pos=j;
                Min=cost[j];
            }
        }
        vis[pos]=1;
        for(int j=0;j<n;j++)
        {
            if(vis[j]==0&&mp[pos][j]<cost[j])
            {
                cost[j]=mp[pos][j];
            }
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();

        /**无语,这个必须放在这*/
        memset(vis,0,sizeof(vis));

        int a,b,v;          //表示两个结点a、b与相连接的一条边上的权值v
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&v);
            if(mp[a][b]>v)
            {
                mp[a][b]=mp[b][a]=v;     //由于是无向图,所有保持对称矩阵
            }
        }
        Prim();

        int sum=0;        //记录最小生成树所有边的权值
        for(int i=1;i<n;i++)
        {
            sum+=cost[i];
        }
        if(sum>Max)
            printf("impossible\n");
        else
            printf("%d\n",sum);
        printf("\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值