﻿HDU 1875 畅通工程再续(Prime最小生成树)-Ocrosoft

# 畅通工程再续

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 23961    Accepted Submission(s): 7724

Problem Description

Input

Output

Sample Input
```
2
2
10 10
20 20
3
1 1
2 2
1000 1000

```

Sample Output
```
1414.2
oh!

```

Author
8600

Solution

```#include <set>
#include <map>
#include <list>
#include <cmath>
#include <stack>
#include <queue>
#include <ctime>
#include <string>
#include <cstdio>
#include <vector>
#include <cctype>
#include <climits>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ms(a) memset(a,0,sizeof(a))
#define INF INT_MAX
#define MAXN 10000+10
using namespace std;
int n,m;
double mp[MAXN][MAXN],lowcast[MAXN];
bool vis[MAXN];
struct Point
{
double x,y;
double dis(Point p)
{
return sqrt(abs(x-p.x)*abs(x-p.x)+abs(y-p.y)*abs(y-p.y));
}
};
double prime(int u0)
{
double ans=0;
int pos=u0;//pos记录为起点
ms(vis),vis[u0]=1;//清空vis数组,标记起点
for(int i=1; i<=n; i++)//初始化lowcast数组
if(i!=pos)lowcast[i]=mp[pos][i];
for(int i=1; i<n; i++)
{
double minn=INF;
for(int j=1; j<=n; j++) //找到没访问过的而且最近的邻近点
if(!vis[j]&&minn>lowcast[j])minn=lowcast[j],pos=j;
if(minn==INF)return 0;
ans+=minn;
vis[pos]=1;//标记这个邻近点
for(int j=1; j<=n; j++) //更新lowcast数组
if(!vis[j]&&lowcast[j]>mp[pos][j])lowcast[j]=mp[pos][j];
}
return ans;
}
int main()
{
int N;
cin>>N;
while(N--)
{
cin>>n;
vector<Point> v;
Point t;
v.push_back(t);
for(int i=1;i<=n;i++)
{
cin>>t.x>>t.y;
v.push_back(t);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
mp[i][j]=(i==j?0:v[i].dis(v[j]));
if((mp[i][j]>0&&mp[i][j]<10)||mp[i][j]>1000)mp[i][j]=INF;
}
}
double ans=prime(1);
if(ans)printf("%.1lf\n",ans*100);
else printf("oh!\n");
}
return 0;
}
```