• nyoj 118 修路方案(最小生成树删边求多个最小生成树)


    修路方案

    时间限制: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)
    样例输入
    2
    3 3
    1 2 1
    2 3 2
    3 1 3
    4 4
    1 2 2
    2 3 2
    3 4 2
    4 1 2
    样例输出
    No
    Yes

    题解:此题的边数较多,不能使用邻接矩阵存边,即不能使用prime算法,用 kruskal算法,先找到一个最小生成树记录下构成它的所有的边,然后再遍历这颗树的边一条条删去查找
    是否有另一颗最小树
    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<cstdio> 
    #include<string>
    #include<math.h>
    #include<algorithm>
    #define LL long long
    #define PI atan(1.0)*4
    #define DD double
    #define MAX 200100
    #define mod 100
    #define dian 1.000000011
    #define INF 0x3f3f3f
    using namespace std;
    int set[MAX];
    int a[510],b[510],c[510];
    struct record
    {
    	int beg;
    	int end;  
    	int ju;  //两村庄之间距离 
    }s[MAX];
    int find(int fa)  //寻找根节点 
    {
    	int ch=fa;
    	int t;
    	while(fa!=set[fa])
    	fa=set[fa];
    	while(ch!=fa)
    	{
    		t=set[ch];
    		set[ch]=fa;
    		ch=t;
    	}
    	return fa;
    }
    void mix(int x,int y) //合并已有村庄 
    {
    	int fx,fy;
    	fx=find(x);
    	fy=find(y);
    	if(fx!=fy)
    	set[fx]=fy;
    }
    bool cmp(record a,record b)
    {
    	return a.ju<b.ju;   //将两村庄之间距离从小到大排列 
    }
    int main()
    {
    	int n,m,j,i,sum,l,t,k;
    	scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%d%d",&n,&m);
    		for(j=1;j<=n;j++)
    			set[j]=j;
    		for(i=0;i<m;i++)
    			scanf("%d%d%d",&s[i].beg,&s[i].end,&s[i].ju);
    		sort(s,s+m,cmp);
    		sum=0;k=0;	
    		for(i=0;i<m;i++)
    		{
    			if(find(s[i].beg)!=find(s[i].end))  //选择最短路径 
    			{
    				a[k++]=i;
    			    mix(s[i].beg,s[i].end);   
    			    sum+=s[i].ju;
    			}	    
    		}
    		int flag=0;
    		int ant=0;int op;
    		for(i=0;i<k;i++)
    		{
    			for(j=1;j<=n;j++)
    			    set[j]=j;
    			op=s[a[i]].ju;
    			s[a[i]].ju=INF;
    			sort(s,s+n,cmp);
    			int ans=0;
    			for(j=0;j<m;j++)
    			{
    				if(find(s[j].beg)!=find(s[j].end))  //选择最短路径 
    			    {
    				    mix(s[j].beg,s[j].end);   
    				    ans+=s[j].ju;
    			    }
    			}
    			s[m-1].ju=op;//这里注意将删去的边还原 
    			sort(s,s+n,cmp);
    			if(ans==sum)
    			{			
    				flag=1;
    				break;
    			}
    	    }
    	    if(flag) printf("Yes
    ");
    	    else printf("No
    ");
    	}
    	return 0;
    }
    
     
    

      

  • 相关阅读:
    WorldWind源码剖析系列:下载请求类DownloadRequest
    WorldWind源码剖析系列:网络下载类WebDownload
    WorldWind源码剖析系列:地形瓦片类TerrainTile和地形瓦片服务类TerrainTileService
    WorldWind源码剖析系列:下载队列类DownloadQueue
    C#游戏开发中快速的游戏循环
    C#游戏开发中精确的时间调配
    C#中XmlSerializer实现序列化浅析
    Vue 组件通信(组件间通信)
    Vue 组件通信(子组件向父组件传递数据)
    Vue props 单向数据流
  • 原文地址:https://www.cnblogs.com/tonghao/p/5341601.html
Copyright © 2020-2023  润新知