zoukankan      html  css  js  c++  java
  • poj 1679 判断最小生成树是否唯一(kruskal)

    判断最下生成树是否唯一的思路:

    1、对图中的每一条边,扫描其他边,如果存在相同权值的边,则对该边做标记。

    2、然后用Kruskal算法或Prim算法求MST。

    3、求得MST后,如果该MST中未包含做了标记的边,即可判断MST唯一;如果包含做了标记的边,则依次去掉这些边再求MST,如果求得的MST权值和原来的MST的权值一样,即可判断MST不唯一。

    针对poj 1679这题,采用Kruskal算法求MST,并判断MST是否唯一:

    代码如下:

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 const int N=110;
      5 using namespace std;
      6 
      7 struct Edge{
      8     int u,v,w;  //边的顶点、权值
      9     bool operator < (const Edge &p) const {
     10         return w<p.w;
     11     }
     12     int equal; //标记,1表示存在权值相同的边,0表示不存在
     13     int used;//在第一次求得的MST中,是否包含该边
     14     int del;  //1删除,0未删除
     15 }edge[N*N];
     16 
     17 int n,m;
     18 bool first;
     19 int parent[N];
     20 
     21 //初始化
     22 void UFset(){
     23     for(int i=0;i<n;i++){
     24         parent[i]=-1;
     25     }
     26 }
     27 
     28 int Find(int x){
     29     int s;
     30     for(s=x;parent[s]>=0;s=parent[s]);
     31     //压缩路径,优化
     32     while(s!=x){
     33         int temp=parent[x];
     34         parent[x]=s;
     35         x=temp;
     36     }
     37     return s;
     38 }
     39 
     40 //合并
     41 void Union(int R1,int R2){
     42     int r1=Find(R1);
     43     int r2=Find(R2);
     44     int temp=parent[r1]+parent[r2];
     45     if(parent[r1]>parent[r2]){
     46         parent[r1]=r2;
     47         parent[r2]=temp;
     48     }else {
     49         parent[r1]=temp;
     50         parent[r2]=r1;
     51     }
     52 }
     53 
     54 int kruskal(){
     55     int sumweight=0,num=0;
     56     int u,v;
     57     UFset();
     58     for(int i=0;i<m;i++){
     59         if(edge[i].del==1)continue;//忽略去掉的边
     60         u=edge[i].u,v=edge[i].v;
     61         if(Find(u)!=Find(v)){
     62             sumweight+=edge[i].w;
     63             num++;
     64             Union(u,v);
     65             if(first)edge[i].used=1;
     66         }
     67         if(num>=n-1)break;
     68     }
     69     return sumweight;
     70 }
     71 
     72 int main(){
     73     int u,v,w,t;
     74     scanf("%d",&t);
     75     while(t--){
     76         scanf("%d%d",&n,&m);
     77         for(int i=0;i<m;i++){
     78             scanf("%d%d%d",&u,&v,&w);
     79             edge[i].u=u-1,edge[i].v=v-1,edge[i].w=w;
     80             edge[i].equal=0,edge[i].used=0,edge[i].del=0;
     81         }
     82         // 标记权值相同的边
     83         for(int i=0;i<m;i++){
     84             for(int j=0;j<m;j++){
     85                 if(i==j)continue;
     86                 if(edge[j].w==edge[i].w){
     87                     edge[i].equal=1;
     88                 }
     89             }
     90         }
     91         sort(edge,edge+m);
     92         first=true;
     93         int weight1=kruskal(),weight2;//第一次求MST
     94         first=false;
     95         int tag=1;
     96         for(int i=0;i<m;i++){
     97             if(edge[i].used&&edge[i].equal){
     98                 edge[i].del=1;
     99                 weight2=kruskal();
    100                 if(weight1==weight2){
    101                     printf("Not Unique!\n");
    102                     tag=0;
    103                     break;
    104                 }
    105                 edge[i].del=0;
    106             }
    107         }
    108         if(tag)
    109             printf("%d\n",weight1);
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    3n+1问题
    判断x的m次方和y的m次方末尾三位数是否相等
    OpenJudge 计算概论1007:点评赛车
    整数划分问题【转】
    证明:平面内有5个整点,必有两个点连线的中点为整点【本资源整理自网络】
    欧几里德算法的证明
    导出本地和远程SVN项目, Export remote SVN repository
    Centos7的firewalld配置
    ESXi5.5下的Centos7虚机配置静态IP
    Dubbo消费端错误: ClassNotFoundException: org.apache.zookeeper.proto.WatcherEvent
  • 原文地址:https://www.cnblogs.com/wally/p/2890460.html
Copyright © 2011-2022 走看看