题解 | #还是畅通工程#

还是畅通工程

http://www.nowcoder.com/practice/d6bd75dbb36e410995f8673a6a2e2229

Kruskal

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

const int MAXN = 100;

struct Edge {
    int a;
    int b;
    int weight;
    Edge(int _a, int _b, int _weight) : a(_a), b(_b), weight(_weight) {}
    friend bool operator < (const Edge& e1, const Edge& e2) {
        return e1.weight < e2.weight;  
    }
};

int Find(vector<int>& s, int x) {
    int root = x;
    while (s[root] >= 0) {
        root = s[root];
    }
    while (x != root) {
        int t = s[x];
        s[x] = root;
        x = t;
    }
    return root;
}

void Union(vector<int>& s, int roota, int rootb) {
    if (s[roota] <= s[rootb]) {
        s[roota] += s[rootb];
        s[rootb] = roota;
    }
    else {
        s[rootb] += s[roota];
        s[roota] = rootb;
    }
}

int main() 
{
    int N;
    while (cin >> N) {
        if (N == 0) break;
        vector<Edge> Edges;
        vector<int> s(MAXN,-1);
        int a, b, w;
        int cnt = N*(N-1)/2;
        while (cnt--) {
            cin >> a >> b >> w;   
            Edges.push_back(Edge(a,b,w));
        }
        sort(Edges.begin(), Edges.end());
        int result = 0;
        for (int i = 0; i < Edges.size(); i++) {
            Edge e = Edges[i];
            int roota = Find(s, e.a);
            int rootb = Find(s, e.b);
            if (roota != rootb) {
                result += e.weight;
                Union(s, roota, rootb);
            }
        }
        cout << result << endl;
    }
    return 0;
}

priority_queue + kruskal

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

struct Edge {
	int a;
	int b;
	int weight;
	Edge(int a, int b, int w) : a(a), b(b), weight(w) { }
	friend bool operator < (const Edge& e1, const Edge& e2) {
		return e1.weight > e2.weight;
	}
};

int Find(vector<int>& s, int x) {
	int root = x;
	while (s[root] >= 0) {
		root = s[root];
	}
	while (x != root) {
		int t = s[x];
		s[x] = root;
		x = t;
	}
	return root;
}

void Union(vector<int>& s, int roota, int rootb) {
	if (s[roota] <= s[rootb]) {
		s[roota] += s[rootb];
		s[rootb] = roota;
	}
	else {
		s[rootb] += s[roota];
		s[roota] = rootb;
	}
}

const int MAXN = 100;

int main()
{
	int N;
	while (cin >> N) {
		if (N == 0) break;
		priority_queue<Edge> pq;
		//vector<int> s(N, -1);
        vector<int> s(MAXN, -1);
		int a, b, w;
		int cnt = N * (N - 1) / 2;
		while (cnt--) {
			cin >> a >> b >> w;
			pq.push(Edge(a, b, w));
		}
		int result = 0;
		while (!pq.empty()) {
			Edge e = pq.top();
			pq.pop();
			int roota = Find(s, e.a);
			int rootb = Find(s, e.b);
			if (roota != rootb) {
				result += e.weight;
				Union(s, roota, rootb);
			}
		}
		cout << result << endl;
	}
	return 0;
}

Prim算法 邻接矩阵

#include <iostream>
#include <vector>
#include <queue>
#include <limits.h>
using namespace std;

const int MAXN = 100;

int Prim(vector<vector<int>>& G, int s) {
//lowcost数组存储的是一个顶点v到最小生成树集MST中所有顶点的代价最小的值,初始化为cost(s,v)或者正无穷    
    vector<int> lowCost(MAXN, INT_MAX); 
//将图中的顶点分为了两个集合,collected[i] == true, 表示该顶点已经收录于MST中
    vector<bool> collected(MAXN, false);
// s->w  ---- path[w] = s   初始化为源点s
    vector<int> path(MAXN, s);
    collected[s] = true;
    for (int i = 0; i < G[s].size(); i++) {
        if (G[s][i] == 0) continue;
        lowCost[i] = G[s][i];
    }
    int result = 0;
    while (true) {
        int min = INT_MAX;
        int v;
        for (int i = 0; i < MAXN; i++) {
            if (!collected[i] && lowCost[i] < min) {
                min = lowCost[i];
                v = i;
            }
        }
// 1、顶点全部被收录 
// 2、所有没收录的顶点cost都是无穷大,表明剩下的顶点到最小生成树没有边,图不连通
        if (min == INT_MAX) break;
// 将顶点v收录进入最小生成树集合
        collected[v] = true;
        result += G[path[v]][v];
        for (int i = 0; i < G[v].size(); i++) {
            if (G[v][i] == 0 || collected[i]) continue;
            if (G[v][i] < lowCost[i]) {
                lowCost[i] = G[v][i];
                path[i] = v;
            }
        }
    }
    return result;
}

int main() 
{
    int N;
    while (cin >> N) {
        if (N == 0) break;
        int cnt = N*(N-1)/2;
        vector<vector<int>> G(MAXN, vector<int>(MAXN, 0));
        int a, b, w;
        int s;
        bool flag = true;
        while (cnt--) {
            cin >> a >> b >> w;
            if (flag == true) {
                s = a;
                flag = false;
            }
            G[a][b] = w;
            G[b][a] = w;
        }
        int res = Prim(G, s);
        cout << res << endl;
    }
    return 0;
}

Prim算法 邻接表

#include <iostream>
#include <vector>
#include <queue>
#include <limits.h>
using namespace std;

const int MAXN = 100;

struct Node {
    int v;     //边的终点编号
    int w;     //边权
    Node(int _v, int _w) : v(_v), w(_w) { }
};

int Prim(vector<vector<Node>>& G, int s) {
//lowcost数组存储的是一个顶点v到最小生成树集MST中所有顶点的代价最小的值,初始化为cost(s,v)或者正无穷    
    vector<int> lowCost(MAXN, INT_MAX); 
//将图中的顶点分为了两个集合,collected[i] == true, 表示该顶点已经收录于MST中
    vector<bool> collected(MAXN, false);
    collected[s] = true;
    for (int i = 0; i < G[s].size(); i++) {
        int v = G[s][i].v;
        int w = G[s][i].w;
        lowCost[v] = w;
    }
    int result = 0;
    while (true) {
        int min = INT_MAX;
        int v;
        for (int i = 0; i < MAXN; i++) {
            if (!collected[i] && lowCost[i] < min) {
                min = lowCost[i];
                v = i;
            }
        }
// 1、顶点全部被收录 
// 2、所有没收录的顶点cost都是无穷大,表明剩下的顶点到最小生成树没有边,图不连通
        if (min == INT_MAX) break;
// 将顶点v收录进入最小生成树集合
        collected[v] = true;
        result += min;
        for (int i = 0; i < G[v].size(); i++) {
            int _w = G[v][i].v;
            if (collected[_w]) continue;
            if (G[v][i].w < lowCost[_w]) {
                lowCost[_w] = G[v][i].w;
            }
        }
    }
    return result;
}

int main() 
{
    int N;
    while (cin >> N) {
        if (N == 0) break;
        int cnt = N*(N-1)/2;
        vector<vector<Node>> Adj(MAXN);
        int a, b, w;
        int s;
        bool flag = true;
        while (cnt--) {
            cin >> a >> b >> w;
            if (flag == true) {
                s = a;
                flag = false;
            }
            Adj[a].push_back(Node(b, w));
            Adj[b].push_back(Node(a, w));
        }
        int res = Prim(Adj, s);
        cout << res << endl;
    }
    return 0;
}

prim 邻接表 priority_queue

#include <iostream>
#include <vector>
#include <queue>
#include <limits.h>
using namespace std;

const int MAXN = 100;

struct Node {
    int v;     //边的终点编号
    int w;     //边权
    Node(int _v, int _w) : v(_v), w(_w) { }
};
struct Edge {
    int a;
    int b;
    int weight;
    Edge(int _a, int _b, int _weight) : a(_a), b(_b), weight(_weight) {}
};
struct cmp {
    bool operator()(const Edge& e1, const Edge& e2) {
        return e1.weight > e2.weight;   //按照value从小到大排列
    }
};

int Prim(vector<vector<Node>>& G, int s) {
    vector<int> lowCost(MAXN, INT_MAX); 
    vector<bool> collected(MAXN, false);
    priority_queue<Edge, vector<Edge>, cmp> pq;
    pq.push(Edge(s,s,0));
    int result = 0;
    while (!pq.empty()) {
        Edge e = pq.top();
        pq.pop();
        if (collected[e.b]) continue;
        collected[e.b] = true;
        result += e.weight;
        for (int i = 0; i < G[e.b].size(); i++) {
            int v = G[e.b][i].v;
            int wgt = G[e.b][i].w;
            if (!collected[v] && wgt < lowCost[v]) {
                lowCost[v] = wgt;
                pq.push(Edge(e.b, v, wgt));
            }
        }
    }
    return result;
}

int main() 
{
    int N;
    while (cin >> N) {
        if (N == 0) break;
        int cnt = N*(N-1)/2;
        vector<vector<Node>> Adj(MAXN);
        int a, b, w;
        int s;
        bool flag = true;
        while (cnt--) {
            cin >> a >> b >> w;
            if (flag == true) {
                s = a;
                flag = false;
            }
            Adj[a].push_back(Node(b, w));
            Adj[b].push_back(Node(a, w));
        }
        int res = Prim(Adj, s);
        cout << res << endl;
    }
    return 0;
}

全部评论

相关推荐

11-04 14:10
东南大学 Java
_可乐多加冰_:去市公司包卖卡的
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务