nyoj 修路方案 次小生成树

来源:互联网 发布:pano2vr软件下载 编辑:程序博客网 时间:2024/05/21 07:54

修路方案

时间限制:3000 ms  |  内存限制:65535 KB
难度:5
描述

南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路。

现在已经知道哪些城市之间可以修路,如果修路,花费是多少。

现在,军师小工已经找到了一种修路的方案,能够使各个城市都联通起来,而且花费最少。

但是,南将军说,这个修路方案所拼成的图案很不吉利,想让小工计算一下是否存在另外一种方案花费和刚才的方案一样,现在你来帮小工写一个程序算一下吧。

输入
第一行输入一个整数T(1<T<20),表示测试数据的组数
每组测试数据的第一行是两个整数V,E,(3<V<500,10<E<200000)分别表示城市的个数和城市之间路的条数。数据保证所有的城市都有路相连。
随后的E行,每行有三个数字A B L,表示A号城市与B号城市之间修路花费为L。
输出
对于每组测试数据输出Yes或No(如果存在两种以上的最小花费方案则输出Yes,如果最小花费的方案只有一种,则输出No)
样例输入
23 31 2 12 3 23 1 34 41 2 22 3 23 4 24 1 2
样例输出
NoYes
来源
POJ题目改编
上传者

张云聪



求最小生成树是否唯一,换句话说就是求次小生成树放入权值和是否等于最小生成树的和,等于,不唯一,否则,唯一。

不懂次小生成树的看看这篇文章http://blog.csdn.net/qq_27437781/article/details/70821413

AC代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define MAX 2005const int INF=0x3f3f3f3f;int g[MAX][MAX],dist[MAX],mmax[MAX][MAX];  ///g保存地图  dist保存从起点到其余各点的距离 maxn保存从i到j的最大边权值int pre[MAX]; ///pre保存j的离它最近的是哪个点bool mark[MAX]; ///相当于vis  用来标记该点是否已经用过bool connect[MAX][MAX]; ///保存i-j的那条边是否加入了最小生成树  false 加入 true  没有int mst,mint; ///mst保存最小生成树的权值和int n,m;int prim(){       int res=0,fa,p,min,i,j;       memset(mmax,0,sizeof(mmax));       for(i=1;i<=n;i++)       {              dist[i]=g[1][i];              pre[i]=1;              mark[i]=false;       }       dist[1]=0;       mark[1]=true;       for(i=1;i<n;i++)       {              p=-1;min=INF;              for(j=1;j<=n;j++)              {                     if(!mark[j]&&dist[j]<min)                     {                            p=j;                            min=dist[j];                     }              }              if(p==-1) return res;              mark[p]=true;              res+=dist[p];              fa=pre[p]; ///找到离p最近的点              connect[fa][p]=false;              connect[p][fa]=false;              mmax[fa][p]=min;              ///遍历所有的点 求其余点到p的最大权值              for(j=1;j<=n;j++)                     mmax[j][p]=(mmax[fa][p]>mmax[j][fa])?mmax[fa][p]:mmax[j][fa];              for(j=1;j<=n;j++)              {                     if(!mark[j]&&dist[j]>g[p][j])                     {                            dist[j]=g[p][j];                            pre[j]=p;                     }              }       }       return res;}int main(){       int tc;       scanf("%d",&tc);       while(tc--)       {              scanf("%d %d",&n,&m);              memset(g,INF,sizeof(g));              memset(connect,false,sizeof(connect));              while(m--)              {                     int u,v,c;                     scanf("%d %d %d",&u,&v,&c);                     g[u][v]=c;                     g[v][u]=c;                     connect[u][v]=true;                     connect[v][u]=true;              }              mst=prim();              int i,j;              bool flag=false;              for(i=1;i<=n;i++)                     for(j=1;j<=n;j++)                     {                            ///如果i-j这条边加入了最小生成树 或者i-j这条路不通  continue                            if(connect[i][j]==false||g[i][j]==INF)                                   continue;                            ///如果加入的边和删除的边的大小是一样的  说明次小生成树的权值和等于最小生成树的权值和                            ///也就是说最小生成树不唯一                            if(g[i][j]==mmax[i][j])                            {                                   flag=true;                                   break;                            }                     }              if(flag)                     printf("Yes\n");              else                     printf("No\n");       }       return 0;}



0 0