zoukankan      html  css  js  c++  java
  • 1083: [SCOI2005]繁忙的都市

    1083: [SCOI2005]繁忙的都市

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1611  Solved: 1040
    [Submit][Status][Discuss]

    Description

    城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造。城市C的道路是这样分布的:城市中有n个交叉路口,有些交叉路口之间有道路相连,两个交叉路口之间最多有一条道路相连接。这些道路是双向的,且把所有的交叉路口直接或间接的连接起来了。每条道路都有一个分值,分值越小表示这个道路越繁忙,越需要进行改造。但是市政府的资金有限,市长希望进行改造的道路越少越好,于是他提出下面的要求: 1. 改造的那些道路能够把所有的交叉路口直接或间接的连通起来。 2. 在满足要求1的情况下,改造的道路尽量少。 3. 在满足要求1、2的情况下,改造的那些道路中分值最大的道路分值尽量小。任务:作为市规划局的你,应当作出最佳的决策,选择那些道路应当被修建。

    Input

    第一行有两个整数n,m表示城市有n个交叉路口,m条道路。接下来m行是对每条道路的描述,u, v, c表示交叉路口u和v之间有道路相连,分值为c。(1≤n≤300,1≤c≤10000)

    Output

    两个整数s, max,表示你选出了几条道路,分值最大的那条道路的分值是多少。

    Sample Input

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

    Sample Output

    3 6
                                                                                            [Submit][Status][Discuss]
     
      这是一个最小生成树的问题,用克鲁斯卡尔算法即可解决,题目要求改造的边尽量少,就是要让其生成一个树才能做到,这样选出的道路数量一定是N-1,第一问解决。
    第二问要求取到分值最大的那一个路的分值, 只用克鲁斯卡尔中的并查集是错误的,需要加以改进,标程如下:
     1 //库鲁斯卡尔 
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 const int maxn=500;
     5 const int inf=1e9;
     6 int fa[maxn];
     7 int MAX;
     8 struct node{
     9     int c;
    10     int l1,l2;
    11 };
    12 node edge[250000];
    13 int get_fa(int x){
    14     if(fa[x]!=x) fa[x]=get_fa(fa[x]);
    15     return fa[x];
    16 }
    17 int cmp(const node&a,const node&b){
    18     if(a.c<b.c) return 1;
    19     return 0;
    20 }
    21 int hehe(int x,int y){
    22     int r1=get_fa(x);
    23     int r2=get_fa(y);
    24     if(r1<r2) fa[r2]=r1;
    25     else fa[r1]=r2;
    26 }
    27 int N,M;
    28 int u,v,w;
    29 int tot;
    30 int main(){
    31     cin>>N>>M;
    32     for(int i=1;i<=M;i++){
    33         scanf("%d%d%d",&u,&v,&w);
    34         edge[i].l1=u;
    35         edge[i].l2=v;
    36         edge[i].c=w;
    37     }
    38     for(int i=1;i<=N;i++) fa[i]=i;
    39     sort(edge+1,edge+M+1,cmp);
    40     
    41     for(int i=1;i<=M;i++){
    42         int r1=edge[i].l1;
    43         int r2=edge[i].l2;
    44         if(get_fa(r1)!=get_fa(r2)){
    45             hehe(r1,r2);
    46             tot++;
    47         }
    48         if(tot==N-1){
    49             MAX=edge[i].c;
    50             break;
    51         }
    52         
    53     }
    54     cout<<(N-1)<<" "<<MAX; 
    55     return 0;
    56 }

    下面是错误的hehe()函数:

    1 int hehe(int x,int y){
    2     int r1=get_fa(x);
    3     int r2=get_fa(y);
    4     fa[r1]=r2;
    5 }

    为什么呢,,试一下这组数据:

    4 6
    1 2 1
    1 3 1
    1 4 1
    2 4 1
    2 3 100
    3 4 100

    正确的是3 1 ,而错误的是3 100 。原因是:当第一步让1,2结点合并此时hehe(1,2)后fa[1]=2,fa[2]=2,之后合并1,3,hehe(1,3)后fa[1]=3,fa[2]=2,fa[3]=3,,,,,,相当于1,2断开了,问题就在这里,解决的方法就是让结点都以小的为父亲,就能AC。

  • 相关阅读:
    155. 最小栈
    160. 相交链表
    PAT 1057 Stack
    PAT 1026 Table Tennis
    PAT 1017 Queueing at Bank
    PAT 1014 Waiting in Line
    PAT 1029 Median
    PAT 1016 Phone Bills
    PAT 1010 Radix
    PAT 1122 Hamiltonian Cycle
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/4641664.html
Copyright © 2011-2022 走看看