算法学习【7】—— 1090. Highways

本文通过对比Prim和Kruskal算法解决最小生成树问题的过程,详细记录了一个具体问题的调试经历,并成功找到解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有老同学回家,要过去看看,有点空闲,就看了下Sicily的1090,题目很简单,不难,就是简单的最小生成树。打算直接套用kruskal类(http://blog.youkuaiyun.com/betabin/article/details/7389263),不过,出问题了。不知道哪里错了,不能过,上网搜了些,貌似也过不了了。郁闷。然后换成prim类(http://blog.youkuaiyun.com/betabin/article/details/7386064),过了,说明应该没理解错题目意思。看来之前的kruskal类可能会有点bugs,今晚看看。

(发现bugs了,合并树的时候忘了个取根,已经修改,就过了。这错误,用了2个钟,不行。)

题目:http://soj.me/1090

1090. Highways

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 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. 

Output

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.
This problem contains multiple test cases!
The first line of a multiple input is an integer T, then a blank line followed by T input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.
The output format consists of T output blocks. There is a blank line between output blocks.

Sample Input

1

3
0 990 692
990 0 179
692 179 0

Sample Output

692

Prim代码如下:Kruskal代码在更下……

// Problem#: 1090
// Submission#: 1301504
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <iostream>
#include <queue>
#include <cstring>

#define MAX_VERTEX 502
#define MAX_EDGE 250003
#define AL_END -1

using namespace std;

struct Edge
{
    int next;
    int vertex;
    int cost;
};

struct Vertex 
{
    int cost;
    int vertex;
};

bool operator <(const Vertex &a, const Vertex &b)
{
    return a.cost > b.cost;
}

Edge edge[MAX_EDGE];

class AlGraph
{
public:
    int smallestCost;
    int max;
    void prim();

private:
    int vertexNum;
    int edgeNum;
    int AlVertex[MAX_VERTEX];
    //Edge edge[MAX_EDGE];
    bool vertexDealed[MAX_VERTEX];
    priority_queue<Vertex> primQueue;

    void initialize();
    void getData();
};

void AlGraph::initialize()
{
    smallestCost = 0;
    max = 0;

    memset(AlVertex, AL_END,sizeof(AlVertex));
    memset(vertexDealed, 0, sizeof(vertexDealed));

    while (!primQueue.empty())
    {
        primQueue.pop();
    }
}

void AlGraph::getData()
{
    initialize();

    cin >> vertexNum;
    edgeNum = vertexNum * vertexNum;
    int source, destination, cost;
    int ip = 0;
    for (source = 0; source < vertexNum; source++)
    {
        for (destination = 0; destination < vertexNum; destination++)
        {
            cin >> cost;
            edge[ip].next = AlVertex[source];
            edge[ip].cost = cost;
            edge[ip].vertex = destination;
            AlVertex[source] = ip++;
        }
        
    }
}

void AlGraph::prim()
{
    getData();

    int gotNum = 0;

    Vertex firstVertex;
    firstVertex.cost = 0;
    firstVertex.vertex = 0;
    primQueue.push(firstVertex);

    while (gotNum < vertexNum)
    {
        Vertex nowvertex = primQueue.top();
        primQueue.pop();

        if (vertexDealed[nowvertex.vertex])
        {
            continue;
        }

        gotNum++;
        smallestCost += nowvertex.cost;

        if (nowvertex.cost > max)
        {
            max = nowvertex.cost;
        }
        
        vertexDealed[nowvertex.vertex] = true;

        for (int i = AlVertex[nowvertex.vertex]; i != AL_END; i = edge[i].next)
        {
            if (!vertexDealed[edge[i].vertex])
            {
                nowvertex.cost = edge[i].cost;
                nowvertex.vertex = edge[i].vertex;
                primQueue.push(nowvertex);
            }
        }
    }
}

int main()
{
    int size;
    AlGraph test;

    cin >> size;

    while (size--)
    {
        test.prim();
        cout <<test.max << endl;
        if (0 != size)
        {
            cout << endl;
        }
        
    }

    return 0;
}                                 

Kruskal代码如下:

#include <iostream>
#include <queue>
#include <stdio.h>

#define MAX_VERTEX 502

using namespace std;

struct Edge 
{
	int source;
	int destination;
	int cost;
};

bool operator < (const Edge &a, const Edge &b)
{
	return a.cost > b.cost;
}

class Graph
{
public:
	int allCost;
	int vertexNum;
	int edgeNum;

	void kruskal();

private:
	int vertexRoot[MAX_VERTEX];                 //Save the root of the tree the node belong to.
	//Sometimes it just save node's father.
	priority_queue<Edge> kruskalQueue;          //Save all edges.

	void getData();
	void initialize();

	void rootReset();                           //Reset all root of each vertex.
	void refreshRoot(int node, int root);       //Update the root of the node and its ancestors.
	int findRoot(int node);                     //Find the root of the tree the node belong to.
	void unionTree(int nodeA, int nodeB);       //Set nodeB as nodeA's father.

	int find(int node);
};

void Graph::rootReset()
{
	for (int i = 0; i < vertexNum; i++)
	{
		vertexRoot[i] = i;
	}
}

void Graph::initialize()
{
	allCost = 0;
	vertexNum = 0;
	edgeNum = 0;

	while (!kruskalQueue.empty())
	{
		kruskalQueue.pop();
	}

	getData();
	rootReset();
}

void Graph::getData()
{
	int i;
	int j;
	Edge inputEdge;
	//cin >> vertexNum;
	scanf("%d", &vertexNum);
	edgeNum = vertexNum * vertexNum;
	for (i = 0; i < vertexNum; i++)
	{
		inputEdge.source = i;
		for (j = 0; j < vertexNum; j++)
		{
			inputEdge.destination = j;
			//cin >> inputEdge.cost;
			scanf("%d", &inputEdge.cost);
			kruskalQueue.push(inputEdge);
		}

	}
}

void Graph::refreshRoot(int node, int root)
{
	int father;

	while (root != vertexRoot[node])
	{
		father = vertexRoot[node];
		vertexRoot[node] = root;
		node = father;
	}
}

int Graph::findRoot(int node)
{
	int rootNode = node;
	while (vertexRoot[rootNode] != rootNode)
	{
		rootNode = vertexRoot[rootNode];
	}

	refreshRoot(node, rootNode);

	return rootNode;
}

void Graph::unionTree(int nodeA, int nodeB)
{
	vertexRoot[vertexRoot[nodeA]] = vertexRoot[nodeB];
}

void Graph::kruskal()
{
	initialize();

	int gotEdgeNum = 0;
	int edgeNeeded = vertexNum - 1;
	Edge currentEdge;

	while (!kruskalQueue.empty() && gotEdgeNum < edgeNeeded)
	{
		currentEdge = kruskalQueue.top();
		kruskalQueue.pop();

		if (findRoot(currentEdge.source) != findRoot(currentEdge.destination))
		{
			unionTree(currentEdge.source, currentEdge.destination);
			allCost += currentEdge.cost;
			gotEdgeNum++;
		}
	}

	//cout << currentEdge.cost;
	printf("%d\n", currentEdge.cost);
}

int main()
{
	int size;
	Graph test;

	//cin >> size;
	scanf("%d", &size);
	while (size--)
	{
		test.kruskal();
		//cout << endl;
		if (0 != size)
		{
			//cout << endl;
			printf("\n");
		}

	}

	return 0;
}                                 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值