Highways(POJ—2485)

简介: Highways(POJ—2485)

题目:

Flatopia岛国完全平坦。不幸的是,Flatopia的公共高速公路系统非常糟糕。弗拉托利亚政府意识到了这个问题,并且已经建造了一些连接一些最重要城镇的高速公路。但是,仍有一些城镇无法通过高速公路抵达。有必要建造更多的高速公路,以便能够在不离开高速公路系统的情况下在任何一对城镇之间行驶。

Flatopian城镇的编号从1到N,城镇i的位置由笛卡尔坐标(xi,yi)给出。每条高速公路连接两个城镇。所有高速公路(原始高速公路和要建造的高速公路)都遵循直线,因此它们的长度等于城镇之间的笛卡尔距离。所有高速公路都可以在两个方向使用。高速公路可以自由地相互交叉,但司机只能在位于两条高速公路尽头的小镇的高速公路之间切换。

Flatopian政府希望最大限度地降低建设新高速公路的成本。但是,他们希望保证每个城镇都可以从其他城镇到达公路。由于Flatopia是如此平坦,高速公路的成本总是与其长度成正比。因此,最便宜的高速公路系统将是最小化总公路长度的系统。

Input

输入包括两部分。第一部分描述了该国的所有城镇,第二部分描述了所有已建成的高速公路。

输入文件的第一行包含一个整数N(1 <= N <= 750),表示城镇数量。接下来的N行每行包含两个整数,xi和yi由空格分隔。这些值给出了第i个城镇的坐标(对于i从1到N)。坐标的绝对值不超过10000.每个城镇都有一个独特的位置。

下一行包含单个整数M(0 <= M <= 1000),表示现有高速公路的数量。接下来的M行每行包含一对由空格分隔的整数。这两个整数给出了一对已经通过高速公路连接的城镇号码。每对城镇至少由一条高速公路连接。

Output

为每条新高速公路写一条输出线,以便连接所有城镇,尽可能减少新高速公路的总长度。每条高速公路都应该通过打印这条高速公路连接的城镇号码来展示,并以空间隔开。

如果不需要建立新的高速公路(所有城镇都已连接),则应创建输出文件,但应该为空。

Sample Input

9
1 5
0 0 
3 2
4 5
5 1
0 4
5 2
1 2
5 3
3
1 3
9 7
1 2

Sample Output

1 6
3 7
4 9
5 7
8 3

解题思路:给定n 个点的坐标,然后又给m个边表示该两个点已经连接起来不需要再建立高速公路。这个题考察的是Prim最短生成树算法,不过该题不是让我们求的是最短总距离,而是求出每一次所建立的边,既头结点和当前结点。

Code:

#include<stdio.h>
#include<string.h>
#include<math.h>
struct node
{
  int x;
  int y;  
}q[2000];
int e[2000][2000],book[5000],dis[50000],f[50000];//f[]是记录头结点的
int inf=999999999;
int count,sum;
int main()
{
  int i,j,k,min,n,m,b,t1,t2;
  while(scanf("%d",&n)!=EOF)
  {
    count=0;
    memset(book,0,sizeof(book));
    memset(dis,0,sizeof(dis));
    memset(f,0,sizeof(f));//数组清零
    for(i=1;i<=n;i++)
      scanf("%d%d",&q[i].x,&q[i].y);
    scanf("%d",&m);

    for(i=1;i<=n;i++)
      for(j=1;j<=n;j++)
        if(i==j)  e[i][j]=0;
        else        e[i][j]=inf;
    for(i=1;i<n;i++)
      for(j=i+1;j<=n;j++)
        e[i][j]=e[j][i]=((q[i].x-q[j].x)*(q[i].x-q[j].x)+(q[i].y-q[j].y)*(q[i].y-q[j].y));
    for(i=1;i<=m;i++)
    {
      scanf("%d%d",&t1,&t2);//已经建立的点就让两点之间距离的边为0
      e[t1][t2]=e[t2][t1]=0;
    }
    for(i=1;i<=n;i++)
      f[i]=1;//初始让所有头结点都为 1
    for(i=1;i<=n;i++)
      dis[i]=e[1][i];
    book[1]=1;
    count++;
    while(count<n)
    {
      min=inf;
      for(i=1;i<=n;i++)
      {
        if(book[i]==0&&dis[i]<min)
        {
          min=dis[i];
          j=i;
        }
      }
      book[j]=1;
      count++;
      if(e[f[j]][j]!=0)//输出要建立所要建立边的两点
        printf("%d %d\n",f[j],j);
      for(k=1;k<=n;k++)
      {
        if(book[k]==0&&dis[k]>e[j][k])
        {
          dis[k]=e[j][k];
          f[k]=j;//更新头结点
        } 
      }
    }   
  }
  return 0;
}

注意:题中的样例给出是随机的,也就是说求得的样例只要所对应的边一样就行了。

相关文章
|
6月前
|
算法
Wormholes—POJ3259
Wormholes—POJ3259
|
存储
|
算法框架/工具
POJ 2262 Goldbach's Conjecture
POJ 2262 Goldbach's Conjecture
137 0
F-POJ-3414 Pots
POJ-3414 Time Limit:1000 ms Memory Limit:65536 K Description You are given two po...
1002 0
poj 3664
http://poj.org/problem?id=3664 进行两轮选举,第一轮选前n进入第二轮,第二轮选最高   #include #include using namespace std; struct vote { int a,b; int c; ...
735 0
POJ 2487 Stamps
Description Background Everybody hates Raymond. He’s the largest stamp collector on planet earth and because of that he always makes fun of all the others at the stamp collector parties.
1064 0
|
人工智能
POJ 1936 All in All
Description You have devised a new encryption technique which encodes a message by inserting between its characters randomly generated strings in a clever way.
791 0