连接格点(kruskal)

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1010,M=N*N,K=2*N*N;
int p[M],g[N][N],n,m,cnt;
struct node{
    int a,b,dist;
}edges[K];
int find(int x){
    if(p[x]!=x)return p[x]=find(p[x]);
    return p[x];
}
void get_top(){
    int dx[4]={0,1,0,-1};
    int dy[4]={1,0,-1,0};
    int dw[4]={2,1,2,1};
    for(int z=1;z>=0;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 a=i+dx[u],b=j+dy[u],w=dw[u];
			            if(a<=0||a>n||b<=0||b>m)continue;
			            int x1=g[i][j],x2=g[a][b];
			            if(x1<x2)
			            edges[cnt++]={x1,x2,w};
			        }
}
int main()
{
    cin>>n>>m;
    int res=0;
    for(int t=1,i=1;i<=n;i++)
    	for(int j=1;j<=m;j++,t++)
    		g[i][j]=t; 
    for(int i=1;i<=n*m;i++)
    	p[i]=i;
    int x1,y1,x2,y2;
    while(cin>>x1>>y1>>x2>>y2){
        int a=g[x1][y1],b=g[x2][y2];
        p[find(a)]=p[find(b)];
    }
    get_top();
    for(int i=0;i<cnt;i++){
        int a=find(edges[i].a),b=find(edges[i].b),w=edges[i].dist;
        if(a!=b){
            p[a]=b;
            res+=w;
        }
    }
    cout<<res<<endl;
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
解法:最短连线问题可以使用最小生成树算法来解决,其中最常用的算法是Prim算法和Kruskal算法。 以下是一个基于Prim算法的Python实现: ```python import random import sys import pygame # 定义方格地图大小 MAP_WIDTH = 800 MAP_HEIGHT = 600 # 定义方格大小 GRID_SIZE = 10 # 定义颜色 BLACK = (0, 0, 0) WHITE = (255, 255, 255) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) # 定义连线规则 LINE_RULES = [(0, 1), (1, 0), (1, 1), (-1, 1)] # 定义节点类 class Node: def __init__(self, x, y): self.x = x self.y = y self.edges = [] def add_edge(self, node, weight): self.edges.append((node, weight)) def __str__(self): return f"({self.x}, {self.y})" # 定义函数:生成随机节点 def generate_random_nodes(num_nodes): nodes = [] for i in range(num_nodes): x = random.randint(0, MAP_WIDTH // GRID_SIZE - 1) y = random.randint(0, MAP_HEIGHT // GRID_SIZE - 1) nodes.append(Node(x, y)) return nodes # 定义函数:计算两个节点之间的距离 def calculate_distance(node1, node2): return ((node1.x - node2.x) ** 2 + (node1.y - node2.y) ** 2) ** 0.5 # 定义函数:生成最小生成树 def generate_minimum_spanning_tree(nodes): start_node = nodes[0] visited = set([start_node]) edges = [] while len(visited) < len(nodes): min_edge = None for node in visited: for edge in node.edges: if edge[0] not in visited: if min_edge is None or edge[1] < min_edge[1]: min_edge = (node, edge[0], edge[1]) edges.append(min_edge) visited.add(min_edge[1]) return edges # 定义函数:绘制节点和连线 def draw_nodes_and_edges(screen, nodes, edges): for node in nodes: pygame.draw.rect(screen, BLACK, (node.x * GRID_SIZE, node.y * GRID_SIZE, GRID_SIZE, GRID_SIZE)) for edge in edges: pygame.draw.line(screen, RED, (edge[0].x * GRID_SIZE + GRID_SIZE // 2, edge[0].y * GRID_SIZE + GRID_SIZE // 2), (edge[1].x * GRID_SIZE + GRID_SIZE // 2, edge[1].y * GRID_SIZE + GRID_SIZE // 2)) # 定义函数:生成节点之间的连线 def generate_edges(nodes, line_rules): for i in range(len(nodes)): for j in range(i + 1, len(nodes)): node1 = nodes[i] node2 = nodes[j] distance = calculate_distance(node1, node2) if (node1.x == node2.x or node1.y == node2.y) and (0, abs(node1.y - node2.y)) in line_rules: node1.add_edge(node2, distance) node2.add_edge(node1, distance) elif (abs(node1.x - node2.x) == abs(node1.y - node2.y)) and (abs(node1.x - node2.x), abs(node1.y - node2.y)) in line_rules: node1.add_edge(node2, distance) node2.add_edge(node1, distance) # 定义主函数 def main(num_nodes, line_rules): # 初始化pygame pygame.init() # 创建屏幕 screen = pygame.display.set_mode((MAP_WIDTH, MAP_HEIGHT)) # 生成随机节点 nodes = generate_random_nodes(num_nodes) # 生成节点之间的连线 generate_edges(nodes, line_rules) # 生成最小生成树 edges = generate_minimum_spanning_tree(nodes) # 绘制节点和连线 draw_nodes_and_edges(screen, nodes, edges) # 更新屏幕 pygame.display.flip() # 等待退出 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() # 运行主函数 if __name__ == '__main__': main(50, LINE_RULES) ``` 运行结果如下图所示: ![最短连线问题](https://cdn.luogu.com.cn/upload/image_hosting/e2z0jx88.png) 可以看到,程序生成了一个有50个随机节点的最小生成树,并用红色线段连接节点。可以根据需要修改节点数量和连线规则。如果有多种结果,可以使用不同的颜色来显示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值