zoukankan      html  css  js  c++  java
  • 【Uvalive4960】 Sensor network (苗条树,进化版)

    【题意】

      给出N个点,M条边,问这N个点形成的生成树的最大权值边-最小权值边的最小值

    Input
    The input consists of several test cases, separated by single blank lines. Each test case begins with a
    line containing the integer n (2 ≤ n ≤ 350), the number of doors in the building. The following line
    contains another integer, m (n − 1 ≤ m ≤ n(n − 1)/2), the number of sensors in the network. The
    test case finishes with m lines containing a description of each of the m sensors. The i-th of those lines
    contains three integers, a (0 ≤ a ≤ n−1), b (0 ≤ b ≤ n−1) and w (1 ≤ w ≤ 2
    15), in that order. Integers
    a and b represent the pair of doors controlled by the i-th sensor, and w its recommended voltage. You
    can safely assume that there are no two sensors controlling the same two doors.
    The input will finish with a line containing ‘0’.
    Output
    For each case, your program should output a line containing the minimum margin of an admissible
    subset of the sensors.
    Sample Input
    3
    3
    0 1 220
    1 2 120
    2 0 160
    4
    5
    2 3 80
    1 3 80
    0 1 180
    2 1 200
    3 0 140
    0
    Sample Output
    40
    60

    【分析】

      是Uva1395的进化版。

      数据范围大了一点点,不过之前的方法也是够慢的,m^2。

      总结来说,生成树问题其实就是有一棵最小生成树,然后你sm乱枚举一些东西,然后在最小生成树上搞啊搞。。【难道不是么??..

      最喜欢就是加一条边弄一个环然后在环上面又删一条边,就是没add边的时候两个点之间唯一路径上的边的权值求最值。

      这题就是这样啦。

      

      先排序,加边,考虑一下加下去的边是否会形成环,如果形成环的话,就把环内的最小边去掉(因为最长边就是现在ADD的那条边,如果要苗条就让边最小尽量大),然后重新求这棵新的生成树的最小边。等到生成树形成的时候,因为添加进去的新边的权值肯定是最大值的,所以只要只减去之前维护一个的最小值就可以了。

      然后,求路径最小边还有找最短边都是O(n)暴力的。

      总时间复杂度:O(nm)

      之前的方法复杂度是O(m^2),嗯,很多恶心题就是完全图,如果是完全图的话,这样的方法无疑是更优的。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<vector>
      8 using namespace std;
      9 #define Maxn 410
     10 #define INF 0xfffffff
     11 
     12 int n,m;
     13 
     14 struct node
     15 {
     16     int x,y,c;
     17 }t[Maxn*Maxn];
     18 
     19 bool cmp(node x,node y) {return x.c<y.c;}
     20 int mymin(int x,int y) {return x<y?x:y;}
     21 
     22 int fa[Maxn];
     23 
     24 bool vis[Maxn];
     25 int get_lca(int now)
     26 {
     27     int x=t[now].x,y=t[now].y,ans=0;
     28     for(int i=1;i<=n;i++) vis[i]=0;
     29     while(x!=fa[x]) vis[x]=1,x=fa[x]; vis[x]=1;
     30     while(y!=fa[y])
     31     {
     32         if(vis[y]) {ans=y;break;}
     33         y=fa[y];
     34     }
     35     if(ans==0&&vis[y]) ans=y;
     36     // while(x!=fa[x]) vis[x]=0,x=fa[x]; vis[x]=0;
     37     return ans;
     38 }
     39 
     40 int dis[Maxn],mn,cnt;
     41 void ffind(int now)
     42 {
     43     int x=t[now].x,y=t[now].y;
     44     // if(fa[x]!=fa[y]) return;
     45     int lca=get_lca(now);
     46     if(lca==0) return;
     47     int k=INF,kv;
     48     while(x!=lca)
     49     {
     50         if(dis[x]<k)
     51         {
     52             k=dis[x];
     53             kv=x;
     54         }
     55         x=fa[x];
     56     }
     57     while(y!=lca)
     58     {
     59         if(dis[y]<k)
     60         {
     61             k=dis[y];
     62             kv=y;
     63         }
     64         y=fa[y];
     65     }
     66     fa[kv]=kv,dis[kv]=0;
     67     mn=INF;
     68     for(int i=1;i<=n;i++) if(fa[i]!=i)
     69     {
     70         mn=mymin(mn,dis[i]);
     71     }
     72     cnt--;
     73 }
     74 
     75 void add(int now)
     76 {
     77     int x=t[now].x,y=t[now].y,c=t[now].c;
     78     if(fa[x]==fa[y]) return;
     79     if(fa[x]==x) fa[x]=y,dis[x]=c;
     80     else if(fa[y]==y) fa[y]=x,dis[y]=c;
     81     else
     82     {
     83         int xx=x,u=fa[x],dd=dis[x];
     84         while(x!=u)
     85         {
     86             int nu=fa[u],nd=dis[u];
     87             fa[u]=x;
     88             dis[u]=dd;
     89             x=u;u=nu;dd=nd;
     90         }
     91         fa[xx]=y;dis[xx]=c;
     92     }
     93     mn=mymin(mn,c);
     94     cnt++;
     95 }
     96 
     97 int main()
     98 {
     99     while(1)
    100     {
    101         scanf("%d",&n);
    102         if(n==0) break;
    103         scanf("%d",&m);
    104         for(int i=1;i<=m;i++)
    105         {
    106             scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].c);
    107             t[i].x++;t[i].y++;
    108         }
    109         sort(t+1,t+1+m,cmp);
    110         cnt=0;
    111         memset(vis,0,sizeof(vis));
    112         for(int i=1;i<=n;i++) fa[i]=i;
    113         mn=INF;
    114         memset(dis,0,sizeof(dis));
    115         int ans=INF;
    116         for(int i=1;i<=m;i++)
    117         {
    118             ffind(i);
    119             add(i);
    120             if(cnt==n-1) ans=mymin(ans,t[i].c-mn);
    121         }
    122         printf("%d
    ",ans);
    123     }
    124     return 0; 
    125 }
    View Code

    WC这题代码把LA3887 A了!!!!

    2016-11-02 09:52:33

    --------------------------------------------------------------------------

    突然发现这题是删边模版?

  • 相关阅读:
    < java.util >-- Set接口
    Codeforces 627 A. XOR Equation (数学)
    Codeforces 161 B. Discounts (贪心)
    Codeforces 161 D. Distance in Tree (树dp)
    HDU 5534 Partial Tree (完全背包变形)
    HDU 5927 Auxiliary Set (dfs)
    Codeforces 27E. Number With The Given Amount Of Divisors (暴力)
    lght oj 1257
    Codeforces 219D. Choosing Capital for Treeland (树dp)
    Codeforces 479E. Riding in a Lift (dp + 前缀和优化)
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6021836.html
Copyright © 2011-2022 走看看