連線格點【最小生成樹】
阿新 • • 發佈:2021-02-08
技術標籤:最小生成樹
連線格點
思路:把二維座標對映到一維的點上,就是一個最小生成樹問題,再把點連線,先連上下再連左右可以省去排序過程
具體程式碼如下
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010, M = N*N, K = 2*M;
struct Node{
int a, b, w;
}node[K];
int n, m, k;
int idx[N][N];
int p[M];
int find(int x){
if(p[ x] != x) p[x] = find(p[x]);
return p[x];
}
void get_edges()
{
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}, dw[4] = {1, 2, 1, 2};
for (int z = 0; z < 2; z ++ )
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
for (int u = 0; u < 4; u ++ )
if (u % 2 == z)
{
int x = i + dx[u], y = j + dy[u], w = dw[u];
if (x && x <= n && y && y <= m)
{
int a = idx[i][j], b = idx[x][y];
if (a < b) node[k ++ ] = {a, b, w};
}
}
}
int main(){
cin >> n >> m;
for(int i=1; i<=n*m; ++i) p[i] = i;
for(int i=1, t=1; i<=n; ++i)
for(int j=1; j<=m; ++j, ++t)
idx[i][j] = t;
int x1, x2, y1, y2;
while(cin >> x1 >> y1 >> x2 >> y2){
int a = idx[x1][y1], b = idx[x2][y2];
p[find(a)] = find(b);
}
get_edges();
int res = 0;
for(int i=0; i<k; ++i){
int a = node[i].a, b = node[i].b, w = node[i].w;
a = find(a), b = find(b);
if(a != b){
p[a] = b;
res += w;
}
}
cout << res << endl;
return 0;
}