POJ 2421

这道题的教训好惨痛....

首先是由于想当然,导致记录边长的数组大小下意识开成了节点数的大小,直接导致一直RE

此外,关于模板,还是要具体问题具体分析,像这道题,开始利用一个模板中记录已知连通分量的想法以此优化,期望提前结束循环。结果表示是不合适的(1 WA),好在快速反应过来这个问题。

思路很清晰,就是Kruskal,因为题目中关于那G对数的设定基本就指向了利用Kruskal的想法

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int maxn= 105;
const int maxm= maxn*maxn;

struct Edge
{
	int u, v, c;
	Edge(int _u= 0, int _v= 0, int _c= 0) : u(_u), v(_v), c(_c) {}
	bool operator < (const Edge &rhs) const
	{
		return c < rhs.c;
	}
}G[maxm];
int dis[maxn][maxn];
int fa[maxn], rk[maxn];

inline int Find(const int x)
{
	if (x== fa[x]){
		return x;
	}
	return fa[x]= Find(fa[x]);
}
void Union(int x, int y)
{
	x= Find(x);
	y= Find(y);
	if (x== y){
		return;
	}
	if (rk[x]< rk[y]){
		fa[x]= y;
		rk[y]+= rk[x];
	}
	else{
		fa[y]= x;
		rk[x]+= rk[y];
	}
}
void Init(int n)
{
	for (int i= 1; i<= n; ++i){
		fa[i]= i;
		rk[i]= 0;
	}
}
int Kruskal(const int n, const int m)
{
	sort(G, G+m);
	int ans= 0;
	for (int i= 0; i< m; ++i){
		int u= G[i].u, v= G[i].v;
		int f_u= Find(u), f_v= Find(v);
		if (f_u== f_v){
			continue;
		}
		ans+= G[i].c;
		Union(f_u, f_v);
	}

	return ans;
}

int main()
{
	int n, q;
	while (~scanf("%d", &n)){
		int u, v;
		int m= 0;
		Init(n);
		for (int i= 1; i<= n; ++i){
			for (int j= 1; j<= n; ++j){
				scanf("%d", dis[i]+j);
			}
		}
		scanf("%d", &q);
		for (int i= 0; i< q; ++i){
			scanf("%d %d", &u, &v);
			Union(u, v);
			dis[u][v]= dis[v][u]= 0;
		}

		for (int i= 1; i<= n; ++i){
			for (int j= i+1; j<= n; ++j){
				if (dis[i][j] && Find(i)!= Find(j)){
					G[m++]= Edge(i, j, dis[i][j]);
				}
			}
		}

		printf("%d\n", Kruskal(n, m));
	}
	return 0;
}
posted @ 2021-04-13 15:09  IdiotNe  阅读(34)  评论(0编辑  收藏  举报