zoukankan      html  css  js  c++  java
  • UVA10462Is There A Second Way Left? —— 次小生成树 kruskal算法

    题目链接:https://vjudge.net/problem/UVA-10462

    Nasa, being the most talented programmer of his time, can’t think things to be so simple. Recently all his neighbors have decided to connect themselves over a network (actually all of them want to share a broadband internet connection :-)). But he wants to minimize the total cost of cable required as he is a bit fastidious about the expenditure of the project. For some unknown reasons, he also wants a second way left. I mean, he wants to know the second best cost (if there is any which may be same as the best cost) for the project. I am sure, he is capable of solving the problem. But he is very busy with his private affairs(?) and he will remain so. So, it is your turn to prove yourself a good programmer. Take the challenge (if you are brave enough)...

    Input

    Input starts with an integer t ≤ 1000 which denotes the number of test cases to handle. Then follows t datasets where every dataset starts with a pair of integers v (1 ≤ v ≤ 100) and e (0 ≤ e ≤ 200). v denotes the number of neighbors and e denotes the number of allowed direct connections among them. The following e lines contain the description of the allowed direct connections where each line is of the form ‘start end cost’, where start and end are the two ends of the connection and cost is the cost for the connection. All connections are bi-directional and there may be multiple connections between two ends.

    Output

    There may be three cases in the output 1. No way to complete the task, 2. There is only one way to complete the task, 3. There are more than one way. Output ‘No way’ for the first case, ‘No second way’ for the second case and an integer c for the third case where c is the second best cost. Output for a case should start in a new line.

    Sample Input 4 5 4 1 2 5 3 2 5 4 2 5 5 4 5 5 3 1 2 5 3 2 5 5 4 5 5 5 1 2 5 3 2 5 4 2 5 5 4 5 4 5 6 1 0

    Sample Output

    Case #1 : No second way

    Case #2 : No way

    Case #3 : 21

    Case #4 : No second way

    题解:

    1.求次小生成树。但是题目要求可以有重边,而prim算法处理的是点与点的关系,不能(至少很难)处理有重边的图。

    2.求最小生成树,除了prim算法之外,还有kruskal算法,且因为它是直接依据边来进行操作的,所以就能很好地处理重边了。

    3.步骤:先用kruskal算法求出最小生成树,同时记录下最小生成树边。然后枚举删除每一条最小生成树边,再去求最小生成树,最终即可得到次小生成树。

    4.复杂度分析:O(n*m),计算次数为2e4,再乘上case数,计算次数为2e7,所以可行。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 using namespace std;
     6 typedef long long LL;
     7 const double EPS = 1e-6;
     8 const int INF = 2e9;
     9 const LL LNF = 9e18;
    10 const int MOD = 1e9+7;
    11 const int MAXN = 1e2+10;
    12 
    13 struct Edge
    14 {
    15     int u, v, w;
    16     bool operator<(const Edge &a)const{
    17         return w<a.w;
    18     }
    19 }edge[MAXN<<1];
    20 int fa[MAXN], used[MAXN];
    21 
    22 int find(int x) { return fa[x]==-1?x:x=find(fa[x]); }
    23 
    24 int kruskal(int n, int m, int pointed)
    25 {
    26     int cnt = 0, sum = 0;
    27     memset(fa, -1, sizeof(fa));
    28     for(int i = 1; i<=m; i++)
    29     {
    30         if(i==pointed) continue;   //如果是那条被指定删除的最小生成树边,则跳过
    31 
    32         int u = find(edge[i].u);
    33         int v = find(edge[i].v);
    34         if(u!=v)
    35         {
    36             fa[u] = v;
    37             sum += edge[i].w;
    38             ++cnt;  //错误:不能放到下一句里面, 即used[++cnt]=i, 因为这条语句必须要执行!!!
    39             if(pointed==-1) used[cnt] = i;  //如果求最小生成树,则把编号为i的边加入生成树中
    40             if(cnt==n-1) return sum;    //合并了n-1次,已成树,可直接返回
    41         }
    42     }
    43     return cnt<(n-1)?INF:sum;   //当合并次数小于n-1时,不能构成树
    44 }
    45 
    46 int main()
    47 {
    48     int T, n, m;
    49     scanf("%d", &T);
    50     for(int kase = 1; kase<=T; kase++)
    51     {
    52         scanf("%d%d",&n,&m);
    53         for(int i = 1; i<=m; i++)
    54             scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
    55 
    56         sort(edge+1, edge+1+m);
    57 
    58         int t1 = INF, t2 = INF;
    59         t1 = kruskal(n, m, -1);     //求最小生成树
    60         for(int i = 1; i<=n-1; i++) //枚举删除每一条最小生成树边边,求次小生成树
    61         {
    62             int tmp = kruskal(n, m, used[i]);
    63             t2 = min(t2, tmp);
    64         }
    65 
    66         if(t1==INF) //原图不连通,既没有最小生成树
    67             printf("Case #%d : No way
    ", kase);
    68         else if(t2==INF)    //没有次小生成树
    69             printf("Case #%d : No second way
    ", kase);
    70         else
    71             printf("Case #%d : %d
    ", kase, t2);
    72     }
    73 }
    View Code
  • 相关阅读:
    极域电子教室 e-Learning Class V4 2010专业版 学生机 卸载方法
    浅谈IT员工管理
    apacheserver下载、安装、配置
    Android BLE开发之Android手机搜索iBeacon基站
    Qt编程18:Qt调色板QPalette的使用
    二叉树的操作
    Android应用开发多语言drawable目录
    Mybatis文档阅读笔记(明日继续更新...)
    《Spark快速大数据分析》—— 第六章 Spark编程进阶
    Java程序员的日常——SpringMVC+Mybatis开发流程、推荐系统
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7760129.html
Copyright © 2011-2022 走看看