现在的位置: 首页 > 综合 > 正文

POJ 2349 Arctic Network

2013年10月15日 ⁄ 综合 ⁄ 共 1598字 ⁄ 字号 评论关闭

题目链接:http://poj.org/problem?id=2349

————————————————————————————————————————————————

题目大意: 有p个城市,s个卫星,卫星是装在一个城市上的(这点很重要),有卫星的城市之间可以任意通讯。

                    所有城市都装有无线电,没有卫星的城市是用无线电来通讯的,城市间的距离越大,无线电通讯的成本就越高。

                    问,若所有城市都能直接,或者间接连在一起(即该图是连通的),需要用无线电通讯的城市间最大的距离的最小值是多少。

————————————————————————————————————————————————

题目思路:    <克鲁斯卡尔>

即求做一最小生成树,去掉其中的 s-1条 最大的边就可以了。

关于这样做的正确性,可以这么理解。生成最小生成树的过程,也是不断的将点合并的过程, 加一个边,就合并在一个连通分量里。

加了p -s 条边以后,图被分成了几个连通分量,刚好一个连通分量里有一个卫星与另外的连通分量进行通讯。

显然这 p-s条边 每一步都是最优的。

————————————————————————————————————————————————

源代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;

struct et
{
   double val;
   int v;
   int u;

   int operator >(const et &e) const
   {
       if(val>e.val) return true;
       else return false;
   }

}edge[125000];

struct vt
{
    double x;
    double y;
    int fat;
}ver[510];

int s = 0,p = 0;
int k = 0,ans[510],m = 0;

double d(vt a,vt b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

bool cmp(et a,et b)
{
    return !(a>b);
}

int findfat(int i)
{
    int f = 0;

    if(ver[i].fat == i)
      return i;
    else
    {
        f = findfat(ver[i].fat);
        ver[i].fat = f;
        return f;
    }
}

void kruskal()
{
    int i = 0;
    int uf = 0,vf = 0;

    m = 0;
    for(i = 0;i<k;i++)
    {
        if((uf = findfat(edge[i].u)) != (vf = findfat(edge[i].v)))
        {
            ver[uf].fat = vf;                      //不为ver[v].fat,因为vf可能更靠近根。此处WA,一定是更改u的father的father,只是更改u的father是错误的!
            ans[m++] = i;
            if(m>=p-1)
              break;
        }
    }
}

int main()
{
    int n = 0;
    int i = 0,x = 0,y = 0,j = 0;

    scanf("%d",&n);
    while((n--)>0)
    {
        k = 0;
        scanf("%d%d",&s,&p);
        for(i = 1;i<=p;i++)
        {
            scanf("%d%d",&x,&y);
            ver[i].x = x;
            ver[i].y = y;
            ver[i].fat = i;
            for(j = 1;j<i;j++)
            {
                edge[k].v = i;
                edge[k].u = j;
                edge[k++].val = d(ver[i],ver[j]);
            }
        }
        sort(edge,edge+k,cmp);
        kruskal();

        m = m-s;
        if(s == 0)
         m = m-1;
        if(p == 1)
          printf("0.00\n");
        else
          printf("%.2f\n",edge[ans[m]].val);
    }

    return 0;
}

抱歉!评论已关闭.