POJ-2421 Constructing Roads(最小生成树)

There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected.

We know that there are already some roads between some villages and your job is the build some roads such that all the villages are connect and the length of all the roads built is minimum.

Input

The first line is an integer N (3 <= N <= 100), 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, 1000]) between village i and village j.

Then there is an integer Q (0 <= Q <= N * (N + 1) / 2). Then come Q lines, each line contains two integers a and b (1 <= a < b <= N), which means the road between village a and village b has been built.

Output

You should output a line contains an integer, which is the length of all the roads to be built such that all the villages are connected, and this value is minimum.

Sample Input

3
0 990 692
990 0 179
692 179 0
1
1 2

Sample Output

179

题意:n个村要实现相通,有q个村已经实现相通,求剩下的村庄要实现村村通的最小花费。

思路;已经相同的村距离设为0,最小生成树过一遍就好了

prim做法代码

#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstdio>
#include <string>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
//#include <unordered_map>
#define Fbo friend bool operator < (node a, node b)
#define mem(a, b) memset(a, b, sizeof(a))
#define FOR(a, b, c) for (int a = b; a <= c; a++)
#define RFOR(a, b, c) for (int a = b; a >= c; a--)
#define off ios::sync_with_stdio(0)
#define sc(a) scanf("%d",&a) 
bool check1(int a) { return (a & (a - 1)) == 0 ? true : false; }

using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int Maxn = 1005;
const double pi = acos(-1.0);
const double eps = 1e-8;

int vis[1010];//用来标记0和1  表示这个点是否被选择过
int graph[1010][1010];//邻接矩阵用来存储图的信息
int dis[1010];//记录任意一点到这个点的最近距离
int n, m, minn, minid, sum;

int prim()
{
    mem(vis, 0);
    sum = 0;
    for (int i = 1; i <= n; i++){
        dis[i] = graph[1][i];
   //   cout << dis[i] << "——";
    }
  //  cout << endl;
    vis[0] = 1;//选择起点
    for (int i = 2; i <= n; i++)
    {
        minn = INF; //存储找到最小的边
        minid = 0;//存储最小边的节点号
        for (int j = 2; j <= n; j++)
        {
            if (!vis[j] && dis[j] < minn)//循环找出dis的最小边的节点
            {
                minn = dis[j];
                minid = j;
            }
        }
        sum += minn;
        vis[minid] = 1;//表示找到了 
    //⑤找到最小的节点之后更新数组dis
        for (int j = 2; j <= n; j++)//添入新点后更新最小距离
        {
            if (!vis[j])//当加入边之后,更新dis
                dis[j] = min(dis[j],graph[minid][j]);
        }
    }
    return sum;
}
int main(){
    while (~scanf("%d", &n)) {
        FOR(i, 1, n) {
            FOR(j, 1, n) {
                scanf("%d", &graph[i][j]);
            }
        }
        scanf("%d", &m);
        while(m--) {
            int a, b;
            scanf("%d%d", &a, &b);
            graph[a][b] = graph[b][a] = 0;//修建成功距离为0
        }
        printf("%d\n", prim());
    }
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/AlexLINS/p/12659259.html