Highways (最小生成树)

来源:互联网 发布:淘宝售后主管岗位职责 编辑:程序博客网 时间:2024/06/05 20:23

Highways

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 26   Accepted Submission(s) : 9
Problem Description
The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has no public highways. So the traffic is difficult in Flatopia. The Flatopian government is aware of this problem. They're planning to build some highways so that it will be possible to drive between any pair of towns without leaving the highway system.

Flatopian towns are numbered from 1 to N. Each highway connects exactly two towns. All highways follow straight lines. All highways can be used in both directions. Highways can freely cross each other, but a driver can only switch between highways at a town that is located at the end of both highways.

The Flatopian government wants to minimize the length of the longest highway to be built. However, they want to guarantee that every town is highway-reachable from every other town.
 

Input
The first line of input is an integer T, which tells how many test cases followed.<br>The first line of each case is an integer N (3 <= N <= 500), which is the number of villages. Then come N lines, the i-th of which contains N integers, and the j-th of these N integers is the distance (the distance should be an integer within [1, 65536]) between village i and village j. There is an empty line after each test case.
 

Output
For each test case, you should output a line contains an integer, which is the length of the longest road to be built such that all the villages are connected, and this value is minimum.
 

Sample Input
130 990 692990 0 179692 179 0
 

Sample Output
692
 

Source
PKU
 题意:有几个城镇,每两个城镇之间必须得相通,那么修最少的路的其中的最大的一条路径!
思路:

最小生成树问题,prim算法

一、什么是图的最小生成树(MST)?

     不知道大家还记不记得树的一个定理:N个点用N-1条边连接成一个连通块,形成的图形只可能是树,没有别的可能

  一个有N个点的图,边一定是大于等于N-1条的。图的最小生成树,就是在这些边中选择N-1条出来,连接所有的N个点。这N-1条边的边权之和是所有方案中最小的。

Prim算法

Prim算法采用与Dijkstra、Bellman-Ford算法一样的“蓝白点”思想:白点代表已经进入最小生成树的点,蓝点代表未进入最小生成树的点。

算法描述:

以1为起点生成最小生成树,min[v]表示蓝点v与白点相连的最小边权。

MST表示最小生成树的权值之和。

a)初始化:min[v]= ∞(v≠1); min[1]=0;MST=0;

b)for (i = 1; i<= n; i++)

1.寻找min[u]最小的蓝点u。

2.将u标记为白点

3.MST+=min[u]

4.for 与白点u相连的所有蓝点v 

                 if (w[u][v]<min[v])

                      min[v]=w[u][v];

c)算法结束: MST即为最小生成树的权值之和

算法分析&思想讲解:

   Prim算法每次循环都将一个蓝点u变为白点,并且此蓝点u与白点相连的最小边权min[u]还是当前所有蓝点中最小的。这样相当于向生成树中添加了n-1次最小的边,最后得到的一定是最小生成树。

代码:

#include <iostream>#include <stdio.h>#include <cstring>#include <cmath>#include <string>#include <algorithm>using namespace std;int g[1005][1005];   //邻接矩阵int minn[1005]; //minn[i]表示存放蓝点i与白点相连的最小边权int n,i,j;bool u[1005];//表示定点是否加入到生成树中int main(){    int T;    cin>>T;    while(T--)    {        cin>>n;        {            for(i=1;i<=n;i++)                for(j=1;j<=n;j++)                cin>>g[i][j];        }        memset(minn,0x7f,sizeof(minn));  //注意此处初始化为最大        minn[1]=0;        memset(u,1,sizeof(u));//初始化为1,表示所有顶点都未进入生成树        for(i=1;i<=n;i++)        {            int  k=0;  //注意理解            for(j=1;j<=n;j++)if(u[j]&&minn[j]<minn[k])k=j;//找一个与白点相连的最小的权值并且未进入生成树的k,因为不与白点相连的蓝点未付给正常值,仍是无穷大            u[k]=0;  //标记加入生成树,            for(j=1;j<=n;j++)if(u[j]&&(g[k][j]<minn[j]))minn[j]=g[k][j];//修改与k相连的所有未进入生成树得点        }        int maxx=-1;        for(i=1;i<=n;i++)if(maxx<minn[i])maxx=minn[i];//求最大的一个中间路径        cout<<maxx<<endl;    }    return 0;}
心得:

开始接触图论!

原创粉丝点击