修路方案(次小生成树)

来源:互联网 发布:纯爱社区 域名 编辑:程序博客网 时间:2024/05/21 09:59

描述

南将军率领着许多部队,它们分别驻扎在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

次小生成树次小生成树可由最小生成树换一条边得到

算法:1)先用prim求出最小生成树T,在prim的同时,用一个矩阵max[u][v]记录在树中连接u-v的路径中权值最大的边.2)枚举所有不在T中的边u-v,加入边u-v,删除权值为max[u][v]的边,不断枚举找到次小生成树.

#include <iostream>#include <algorithm>#include <queue>#include <math.h>#include <deque>#include <stack>#include <set>#include <limits>#include <malloc.h>#include <string.h>#include <stdio.h>#include <stdlib.h>.#define MOD 10000#define ll long long#define MAX 100005//#define root 1,m,1#define lson l,mid,rt << 1#define rson mid+1,r,rt << 1 | 1using namespace std;const int INF=0x3f3f3f3f;int g[1100][1100],dist[1100],mmax[1100][1100];int pre[1100];bool mark[1100];bool connect[1100][1100];int mst,mint;int n,m;void 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;//标记所有节点的依附点皆为默认的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 ;              mark[p]=true;//把p放入集合中              res+=min;              fa=pre[p];              connect[fa][p]=false;              connect[p][fa]=false;              mmax[fa][p]=min;              for(j=1;j<=n;j++)//更新权值和依附点              {                     if(!mark[j]&&dist[j]>g[p][j])                     {                            dist[j]=g[p][j];                            pre[j]=p;                     }              }              for(j=1;j<=n;j++)                     mmax[j][p]=(mmax[fa][p]>mmax[j][fa])?mmax[fa][p]:mmax[j][fa];       }       return ;}int main(){       int tc;    //freopen("1.txt","r",stdin);       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;              }              prim();              int i,j;              bool flag=false;              for(i=1;i<=n;i++)                     for(j=1;j<=n;j++)                     {                            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
原创粉丝点击