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

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

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

  • 相关阅读:
    赠与今年的大学毕业生(胡适先生30年代的文章,仍不过时)
    统一管理磁盘上的开源代码
    生成sqlite导入库的做法
    提高二维矢量绘图效率之一般做法
    boost库命名规则的优点
    如何把腾讯微博挂到CSDN博客上
    fatal error C1902 Program database manager mismatch; please check your installation问题的解决
    智能指针变量做函数参数的一个值得注意的地方
    PC会消亡吗?
    软件制造问题的微软答案
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6021836.html
Copyright © 2011-2022 走看看