最小(大)生成树_裸题(HDU-1863,POJ-2377)

(HDU-1863)畅通工程

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 16536    Accepted Submission(s): 6898



Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
 

Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
 

Output
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
 

Sample Input
  
  
3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2 0 100
 

Sample Output
  
  
3 ?
 
这就是一道裸的最小生成树。我用的是Kruskal算法:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int max_e=10000+5;
struct Edge
{
    int u,v;
    int cost;
}e[max_e];
bool cmp(Edge a,Edge b)
{
    return a.cost<b.cost;
}
int father[105];
int find(int x)
{
    if(x!=father[x]) father[x]=find(father[x]);
    return father[x];
}

int main()
{
    int N,M;
    while(scanf("%d%d",&N,&M)!=EOF)
    {
        if(N==0) break;
        for(int i=0;i<N;i++)
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].cost);
        sort(e,e+N,cmp);
        for(int i=1;i<=M;i++)
            father[i]=i;
        int ans=0;
        int point=0;
        for(int i=0;i<N;i++)
        {
            int x=find(e[i].u);
            int y=find(e[i].v); 
            if(x!=y){
                ans+=e[i].cost;
                point++;
                father[y]=x;
            }
        }
        if(point<M-1) printf("?\n");
        else          printf("%d\n",ans);
    }return 0;
}

(POJ-2377)Bad Cowtractors
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 10239 Accepted: 4348

Description

Bessie has been hired to build a cheap internet network among Farmer John's N (2 <= N <= 1,000) barns that are conveniently numbered 1..N. FJ has already done some surveying, and found M (1 <= M <= 20,000) possible connection routes between pairs of barns. Each possible connection route has an associated cost C (1 <= C <= 100,000). Farmer John wants to spend the least amount on connecting the network; he doesn't even want to pay Bessie.

Realizing Farmer John will not pay her, Bessie decides to do the worst job possible. She must decide on a set of connections to install so that (i) the total cost of these connections is as large as possible, (ii) all the barns are connected together (so that it is possible to reach any barn from any other barn via a path of installed connections), and (iii) so that there are no cycles among the connections (which Farmer John would easily be able to detect). Conditions (ii) and (iii) ensure that the final set of connections will look like a "tree".

Input

* Line 1: Two space-separated integers: N and M

* Lines 2..M+1: Each line contains three space-separated integers A, B, and C that describe a connection route between barns A and B of cost C.

Output

* Line 1: A single integer, containing the price of the most expensive tree connecting all the barns. If it is not possible to connect all the barns, output -1.

Sample Input

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

Sample Output

42



这个题目是个裸的最大生成树,原理和最小生成树一个意思,还是用Kruskal算法:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int max_e=20000+5;

struct Edge{
    int u,v;
    int cost;
}e[max_e];

int father[1005];
int Union_Find(int x){
    if(x!=father[x]) father[x]=Union_Find(father[x]);
    return father[x];
}

bool cmp(Edge a,Edge b){
    return a.cost>b.cost;
}

int main()
{
    int N,M;
    scanf("%d%d",&N,&M);
    for(int i=0;i<M;i++){
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].cost);
    }
    sort(e,e+M,cmp);
    for(int i=1;i<=N;i++)
        father[i]=i;
    int point=0;
    int ans=0;
    for(int i=0;i<M;i++){
        int x=Union_Find(e[i].u);
        int y=Union_Find(e[i].v);
        if(x!=y){
            ans+=e[i].cost;
            point++;
            father[y]=x;
        }
    }
    if(point<N-1) printf("-1\n");
    else          printf("%d\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值