zoukankan      html  css  js  c++  java
  • POJ 1679 判断最小树是否唯一

    题意:
         判断最小树是否唯一。
    思路:

         我用了两种方法,主要就是好久没敲了,找个水题练练手,第一种就是先一遍最小生成树,然后枚举最小生成树上的每一条边,然后取消这条边,在跑一遍最小生成树,就这样一直跑最小生成树,如果找到了一颗和之前的那个一样的,那么就是不唯一,第二种方法也是先最小树,然后枚举,在枚举的时候不是继续重新跑,而是断开当前边,把树分成两个集合<两次深搜实现>,然后在枚举这连个集合之间是否可以找到一个可以代替当前枚举的最小树的边,实现复杂度的话应该是第二种快点,但理论上也快不多少,只是为了练练手,在多说一句,第二种方法和求次小树的思路有点像,但是次小树可以再这个上面进行dp优化,其实这个题目也可以直接判断次小树是否等于最小树。好像有点说多了。


    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    
    #define N 110
    
    using namespace std;
    
    typedef struct
    {
       int x ,y ,c;
    }EDGE;
    
    typedef struct
    {
       int to ,next;
    }STAR;
    
    EDGE edge[N*N];
    STAR E[N*N];
    int  map[N][N] ,mer[N] ,mark[N];
    int list[N] ,tot ,mst[N];
    int L[N] ,R[N] ,ll ,rr;
    
    void add(int a, int b)
    {
       E[++tot].to = b;
       E[tot].next = list[a];
       list[a] = tot;
    }
    
    int finds(int x)
    {
       return x == mer[x] ? x : mer[x] = finds(mer[x]);
    }
    
    int minn(int x ,int y)
    {
       return x < y ? x : y;
    }
    
    bool camp(EDGE a ,EDGE b)
    {
       return a.c < b.c;
    }
    
    int MST(int n ,int m)
    {
       for(int i = 1 ;i <= n ;i ++) mer[i] = i;
       int Ans = 0 ,sum = 0;
       memset(list ,0 ,sizeof(list)) ,tot = 1;
       for(int i = 1 ;i <= m ;i ++)
       {
          int xx = finds(edge[i].x);
          int yy = finds(edge[i].y);
          if(xx != yy) 
          {
             Ans += edge[i].c ,sum ++;
             mer[xx] = yy;
             mst[sum] = i;
             add(edge[i].x ,edge[i].y);
             add(edge[i].y ,edge[i].x);
          }
          if(sum == n - 1) break;
       }
       return Ans;
    }
    
    void DFS1(int x)
    {
       for(int k = list[x] ;k ;k = E[k].next)
       {
          int to = E[k].to;
          if(mark[to]) continue;
          mark[to] = 1;
          L[++ll] = to;
          DFS1(to);
       }
    }
    
    void DFS2(int x)
    {
       for(int k = list[x] ;k ;k = E[k].next)
       {
          int to = E[k].to;
          if(mark[to]) continue;
          mark[to] = 1;
          R[++rr] = to;
          DFS2(to);
       }
    }
    
    
    int main ()
    {
       int t ,n ,m ,i ,j ,mk;
       scanf("%d" ,&t);
       while(t--)
       {
           scanf("%d %d" ,&n ,&m);
           for(i = 1 ;i <= n ;i ++)
           for(j = 1 ;j <= n ;j ++)
           map[i][j] = 100000000;
           for(i = 1 ;i <= m ;i ++)
           {
              scanf("%d %d %d" ,&edge[i].x ,&edge[i].y ,&edge[i].c); 
              int x = edge[i].x ,y = edge[i].y;
              map[x][y] = map[y][x] = minn(map[x][y] ,edge[i].c);
          }
          sort(edge + 1 ,edge + m + 1 ,camp);
          int Ans = MST(n ,m);
          if(m == n - 1)
          {
             printf("%d
    " ,Ans);
             continue;
          }
          mk = 0;
          for(i = 1 ;i < n && !mk;i ++)
          {
             memset(mark ,0 ,sizeof(mark));
             int l = edge[mst[i]].x ,r = edge[mst[i]].y;
             mark[l] = mark[r] = 1;
             ll = rr = 0;
             L[++ll] = l ,R[++rr] = r;    
             DFS1(l) ,DFS2(r);
             for(int j = 1 ;j <= ll && !mk;j ++)
             {
                for(int k = 1 ;k <= rr && !mk ;k ++)
                {
                   if(L[j] == edge[mst[i]].x && R[k] == edge[mst[i]].y || L[j] == edge[mst[i]].y && R[k] == edge[mst[i]].x)
                   continue;
                   if(map[L[j]][R[k]] == edge[mst[i]].c) mk = 1;
                }
             }
          }
          mk ? printf("Not Unique!
    "): printf("%d
    " ,Ans);
       }
       return 0;
    }
             
          

  • 相关阅读:
    Effective C++读书笔记~4 设计与声明
    《程序员的自我修养》读书笔记 第十一章 运行库
    C++ 调试问题:对象包含与成员函数不兼容的类型限定符
    Effective C++读书笔记~6 继承与面向对象设计
    C++ lambda表达式
    备战前端
    SQL Server2008 统计某个数据库用户表和行计数方法
    回想
    C# 理解lock
    (原创)Nhibernate对象关系映射的两种方式以及一些注意
  • 原文地址:https://www.cnblogs.com/csnd/p/12062754.html
Copyright © 2011-2022 走看看