zoj2048

题目大意:

Flatopia需要建更多公路,使得开车不离开公路可以到任何两个镇。Flatopian镇从1到N编号并且有坐标。每条公路连接两个镇,所有的公路都是直的。所有的公路都是双向的。公路可以相互交,司机只可以在公路的末端交换。
Flatopian政府想要最小化成本。然而,他们想保证任何两个镇 都是可以到达的。
输入:N,第一行镇子的数量,接下来的N行包括坐标。
接下来的一行M,代表现存铁路的数量,接下来的M行包括 铁路路线

解题思路:

最小生成树问题

代码入下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 755
typedef struct
{
    int x, y;
    int w;
}edge;
edge e[MAX*MAX/2];
int rank[MAX], father[MAX];
int cmp(const void *a, const void *b)
{
    if ((*(edge *)a).w > (*(edge *)b).w)
    return 1;
    return -1;
}
void Make_Set(int x)
{
    father[x] = x;
    rank[x] = 0;
}
int Find_Set(int x)
{
    if (x != father[x])
       father[x] = Find_Set(father[x]);
    return father[x];
}
void Link(int x, int y, int w)
{
    if (rank[x] > rank[y])  father[y] = x;
    else
    {
        father[x] = y;
        if (rank[x] == rank[y])  rank[y]++;
    }
}
void Kruskal(int point_amou, int edge_amou)
{
    int i, x, y;
    qsort(e, edge_amou, sizeof(edge), cmp);
    for (i = 0; i < edge_amou; i++)
    {
        x = Find_Set(e[i].x);
        y = Find_Set(e[i].y);
        if (x != y)  
     {
        Link(x, y, e[i].w);
        printf("%d %d\n", e[i].x+1, e[i].y+1);
     }
    }
}    
int main(void)
{
    int T, N, M, i, j, cnt, s, t;
    int a[755], b[755];
    scanf("%d", &T);
    while(T--)
    {
     scanf("%d", &N);
     for(i = 0; i < N; i++)
     {
        scanf("%d %d", &a[i], &b[i]);
        Make_Set(i);
     }
     cnt = 0;
     for(i = 0; i < N; i++)
     {
        for(j = i+1; j < N; j++)
        {
         e[cnt].x = i;
         e[cnt].y = j;
         e[cnt].w = (a[i]-a[j])*(a[i]-a[j]) + (b[i]-b[j])*(b[i]-b[j]);
         cnt++;
        }
     }
     scanf("%d", &M);
     for(i = 0; i < M; i++)
     {
        scanf("%d %d", &s, &t);
        s--;
        t--;
        s = Find_Set(s);
        t = Find_Set(t);
        Link(s, t, 0);
     }
     Kruskal(N, cnt);
     if(T) printf("\n");

    }
    return 0;
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值