• lightoj 1123 增量最小生成树


    题意:有n个点(1<=n<=200),最多有m( 1<=m<=6000) 条边,依次给出每一条边,要求求每次给出的边组成的图中最小生成树的值是多少。如果给出的边还不足以连接n个点组成树,输出-1;

    分析:

    直接模拟肯定超时,已经预料到了,还是交了一发T表示尊重。。。=v=。

    接下来想到并查集的特点,如果倒过来做的话,反而更加复杂,因为从并查集里删去一条边简直噩梦。

    可以发现,如果有一棵n节点的生成树了,这时候再加入一条边,必定能形成环,那么我们的任务就变成了,如何删去这个环中最大的权值边。

    按照生成树的特点,按边排序后,小的权值是被优先选择的,所以当后面判断到两个点已经在联通分量中时,这条边就是我们要删去的边。

    删边技巧,由于我们还是每次都要排序的(并没有使用数据结构维护边集),所以假设我们的边存在 a[0] ~ a[n - 1] 中,其中a[k] 是我们要删去的边。

    那么我们就 a[k] = a[n - 1] ; n-- ; 

    这样,反正我们下次进行MST的时候还是要sort的,所以数组中的大小位置是无所谓的。

    因为到后面足够多的边的时候,总能产生生成树,产生了生成树之后,边集的大小就不会变了(每次都一定加入一条边,并删去一条边),所以复杂度不会很高。

    教训:

    然而即使知道了这些我还是T了,后来检查许久,发现是pair的锅,原本用来存储边的pair是这样的

    pair<int,pair<int,int> >road[MAXN];

    改成结构体node

    struct node{

    int w , a , b ;

    }road[MAXN];

    以后,就A掉了!

    pair真是慢.........

     1 /* When all else is lost the future still remains. */
     2 /* You can be the greatest */
     3 #define rep(X,Y,Z) for(int X=(Y);X<(Z);X++)
     4 #define drep(X,Y,Z) for(int X=(Y);X>=(Z);X--)
     5 #define fi first
     6 #define se second
     7 #define mk(X,Y) make_pair((X),(Y))
     8 //head
     9 #include <iostream>
    10 #include <stdio.h>
    11 #include <queue>
    12 #include <algorithm>
    13 #include <string>
    14 #include <map>
    15 using namespace std;
    16 #define MAXN 210
    17 #define MAXM 6010
    18 //pair<int,pair<int,int> > road[MAXM];
    19 struct node{
    20     int w , a , b;
    21 }road[MAXM];
    22 int rp[MAXN];
    23 int cnt;
    24 int N;
    25 int f(int x){return rp[x] = (rp[x] == x) ? x : f(rp[x]);}
    26 void init(int n){
    27     rep(i,1,n+1) rp[i] = i;
    28 }
    29 bool cmp(node A , node B){
    30     return A.w < B.w;
    31 }
    32 int mst(){
    33     int ans = 0;
    34     sort(road,road+N,cmp);
    35     int pos = -1;
    36     rep(i,0,N){
    37         int val = road[i].w;
    38         int a = f(road[i].a);
    39         int b = f(road[i].b);
    40         if(a == b){pos = i; continue;}
    41         rp[a] = rp[b] = min(a,b);
    42         ans += val;
    43         cnt--;
    44     }
    45     if(pos != -1) road[pos] = road[--N];
    46     return cnt == 1 ? ans : -1;
    47 }
    48 int main(){
    49     int T;
    50     scanf("%d",&T);
    51     rep(ca,1,T+1){
    52         N = 0;
    53         printf("Case %d:
    ",ca);
    54         int n , m;
    55         scanf("%d %d",&n,&m);
    56         rep(i,0,m){
    57             int a , b , w;
    58             scanf("%d %d %d",&road[N].a,&road[N].b,&road[N].w);
    59             N++;
    60             cnt = n;
    61             init(n);
    62             printf("%d
    ",mst());
    63         }
    64     }
    65     return 0;
    66 
    67 }
  • 相关阅读:
    leetcode5 Longest Palindromic Substring
    leetcode17 Letter Combinations of a Phone Number
    leetcode13 Roman to Integer
    leetcode14 Longest Common Prefix
    leetcode20 Valid Parentheses
    leetcode392 Is Subsequence
    leetcode121 Best Time to Buy and Sell Stock
    leetcode198 House Robber
    leetcode746 Min Cost Climbing Stairs
    tomcat下使用druid配置jnid数据源
  • 原文地址:https://www.cnblogs.com/ticsmtc/p/5943869.html
Copyright © 2020-2023  润新知