kuangbin最小生成树专题

网址:https://vjudge.net/contest/66965#overview

第一题:

poj1251

裸最小生成树

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100500;
struct node
{
    int x;
    int y;
    int w;
}a[maxn];
int n,k;
char s,v;
int cnt;
int w;
int f[30];
int  findf(int x)
{
    if(f[x]==x)
        return x;
    else
    {
        //f[x]=findf(f[x]);
        return findf(f[x]);
    }
}
int join(int x,int y)
{
    int t1=findf(x);
    int t2=findf(y);
    if(t1==t2)
        return 1;
    else
    {
        f[t2]=t1;
        return 0;
    }
}
int cmp(node x,node y)
{
    return x.w<y.w;
}
int main()
{
    while(cin>>n)
    {
        if(n==0)
            break;
        for(int i=1;i<=30;i++)
            f[i]=i;
        cnt=0;
        for(int i=1;i<n;i++)
        {
            cin>>s>>k;
            for(int i=1;i<=k;i++)
            {
                cin>>v>>w;
                a[++cnt].x=s-'A'+1;
                a[cnt].y=v-'A'+1;
                a[cnt].w=w;
            }
        }
        sort(a+1,a+1+cnt,cmp);
        int cot=0;
        int cost=0;
        for(int i=1;i<=cnt;i++)
        {
            if(join(a[i].x,a[i].y)==0)
            {
                cot++;cost+=a[i].w;
            }
            if(cot==n-1)
                break;
        }
        cout<<cost<<endl;
    }
}

 

第二题

poj1287

裸最小生成树

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100500;
struct node
{
    int x,y,w;
}a[maxn];
int f[100];
int cnt,cot;
int n,m;
int x,y,w;
bool cmp(node xx,node yy)
{
    return xx.w<yy.w;
}
int findf(int u)
{
    if(f[u]==u)
        return u;
    else
    {
        f[u]=findf(f[u]);
        return f[u];
    }
}
bool join(int u,int v)
{
    int t1=findf(u);
    int t2=findf(v);
    if(t1==t2)
    {
        return false;
    }
    else
    {
        f[t2]=t1;
        return true;
    }
}
int main()
{
    while(cin>>n>>m)
    {
        if(n==0)
            break;
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y>>w;
            a[i].x=x;
            a[i].y=y;
            a[i].w=w;
        }
        sort(a+1,a+1+m,cmp);
        for(int i=1;i<=n;i++)
            f[i]=i;
        cnt=0;
        int cost=0;
        for(int i=1;i<=m;i++)
        {
            if(join(a[i].x,a[i].y))
            {
                cnt++;
                cost+=a[i].w;
                if(cnt==n-1)
                    break;
            }
        }
        cout<<cost<<endl;
    }
}

 

第三题

poj2031

最小生成树+圆的距离

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn=20050;
struct node
{
    int x,y;
    double w;
}a[maxn];
struct circle
{
    double x,y,z,r;
}c[205];
int f[205];
int n;
int cnt;
int findf(int u)
{
    if(f[u]==u)
        return u;
    else
    {
        f[u]=findf(f[u]);
        return f[u];
    }
}
bool join(int u,int v)
{
    int t1=findf(u);
    int t2=findf(v);
    if(t1==t2)
    {
        return false;
    }
    else
    {
        f[t2]=t1;
        return true;
    }
}
bool cmp(node u,node v)
{
    return u.w<v.w;
}
double juage(int u,int v)
{
    double tmp=sqrt((c[u].x-c[v].x)*(c[u].x-c[v].x)+(c[u].y-c[v].y)*(c[u].y-c[v].y)+(c[u].z-c[v].z)*(c[u].z-c[v].z));
    if(tmp<=(c[u].r+c[v].r))
        return 0;
    else
    {
        double ans=tmp-c[u].r-c[v].r;
        return ans;
    }
}
int main()
{
    while(cin>>n)
    {
        int cot=0;
        if(n==0)
            break;
        for(int i=1;i<=n;i++)
        {
            cin>>c[i].x>>c[i].y>>c[i].z>>c[i].r;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
        {
            if(i==j)
                continue;
            else
            {
                a[++cot].x=i;a[cot].y=j;a[cot].w=juage(i,j);
            }
        }
        for(int i=1;i<=n;i++)
            sort(a+1,a+1+cot,cmp);
        for(int i=1;i<=n;i++)
            f[i]=i;
        cnt=0;
        double cost=0;
        for(int i=1;i<=cot;i++)
        {
            if(join(a[i].x,a[i].y))
            {
                cost+=a[i].w;
                cnt++;
            }
            if(cnt==n-1)
                break;
        }
        printf("%.3f\n",cost);
    }
}

 

第四题:

poj2421

部分边+最小生成树,先把给出的边扔进并查集里

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100500;
struct node
{
    int x,y,w;
}a[maxn];
int g[105][105];
int n,cnt;
int f[105];
int cmp(node x,node y)
{
    return x.w<y.w;
}
int findf(int u)
{
    if(f[u]==u)
        return u;
    else
    {
        f[u]=findf(f[u]);
        return f[u];
    }
}
bool join(int u,int v)
{
    int t1=findf(u);
    int t2=findf(v);
    if(t1==t2)
        return false;
    else
    {
        f[t2]=t1;
        return true;
    }
}
int main()
{
    int x,y;
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            cin>>g[i][j];
    int cost=0;
    int cot=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
    {
        if(i==j)
            continue;
        a[++cot].x=i;a[cot].y=j;a[cot].w=g[i][j];
    }
    sort(a+1,a+1+cot,cmp);
    for(int i=1;i<=n;i++)
        f[i]=i;
    int q;
    cin>>q;
    while(q--)
    {
        cin>>x>>y;
        if(join(x,y))
        {
            cnt++;
        }
        join(x,y);
    }
    for(int i=1;i<=cot;i++)
    {
        if(cnt==n-1)
            break;
        else
        {
            if(join(a[i].x,a[i].y))
            {
            cnt++;
            cost+=a[i].w;
            }
        }
    }
    cout<<cost<<endl;
}

 

第五题:

zoj1586

用prime写的,把边权改成正常边权+点权

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=1005;
const int inf=0x3f3f3f3f;
struct node
{
    int num;
    int dist;
    node(int _num=0,int _dist=0):num(_num),dist(_dist){}
    friend bool operator<(node a,node b)
    {
        return a.dist>b.dist;
    }
};
struct Edge
{
    int next;
    int to;
    int w;
}edge[maxn*maxn];
int g[maxn][maxn];
int c[maxn];
int n;
int visit[maxn];
int dist[maxn];
int head[maxn];
int cnt;
void add(int u,int v,int w)
{
    edge[cnt].next=head[u];
    edge[cnt].to=v;
    edge[cnt].w=w;
    head[u]=cnt++;
}
int prime(int u)
{
    int cost=0;
    fill(dist+1,dist+1+n,inf);
    fill(visit+1,visit+1+n,0);
    dist[u]=0;
    priority_queue<node>q;
    q.push(node(u,dist[u]));
    while(!q.empty())
    {
        node x=q.top();q.pop();
        int now=x.num;
        if(visit[now])
            continue;
        visit[now]=1;
        cost+=dist[now];
        for(int i=head[now];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(visit[v])
                continue;
            if(dist[v]>edge[i].w)
            {
                dist[v]=edge[i].w;
                q.push(node(v,dist[v]));
            }
        }
    }
    return cost;
}
void init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int start=inf;
        int pos=1;
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&c[i]);
            if(start<c[i])
            {
                start=c[i];
                pos=i;
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            scanf("%d",&g[i][j]);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    continue;
                else
                {
                    add(i,j,g[i][j]+c[i]+c[j]);
                }
            }
        }
        int ans=prime(pos);
        cout<<ans<<endl;
    }
}

 

第六题

poj1789

裸最小生成树

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=2050;
const int inf=0x3f3f3f3f;
struct node
{
    int num;
    int dist;
    node(int _num=0,int _dist=0):num(_num),dist(_dist){}
    friend bool operator<(node a,node b)
    {
        return a.dist>b.dist;
    }
};
struct Edge
{
    int next,to,w;
}edge[maxn*maxn];
int head[maxn];
int cnt;
int dist[maxn];
int visit[maxn];
int n;
char s[maxn][10];
void add(int u,int v,int w)
{
    edge[cnt].next=head[u];
    edge[cnt].to=v;
    edge[cnt].w=w;
    head[u]=cnt++;
}
int prime(int u)
{
    int cost=0;
    fill(dist+1,dist+1+n,inf);
    fill(visit+1,visit+1+n,0);
    dist[u]=0;
    priority_queue<node>q;
    q.push(node(u,dist[u]));
    while(!q.empty())
    {
        node x=q.top();q.pop();
        int now=x.num;
        if(visit[now])
            continue;
        visit[now]=1;
        cost+=dist[now];
        for(int i=head[now];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(visit[v])
                continue;
            if(dist[v]>edge[i].w)
            {
                dist[v]=edge[i].w;
                q.push(node(v,dist[v]));
            }
        }
    }
    return cost;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
            break;
        memset(head,-1,sizeof(head));
        cnt=0;
        int tmp;
        for(int i=1;i<=n;i++)
            scanf("%s",s[i]);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                tmp=0;
                if(i==j)
                    continue;
                for(int k=0;k<7;k++)
                {
                    if(s[i][k]!=s[j][k])
                        tmp++;
                }
                add(i,j,tmp);
            }
        }
        int ans=prime(1);
        printf("The highest possible quality is 1/%d.\n",ans);
    }
}

 

第七题

poj2349

反着来,每一个s可以减少s-1条边,先处理s,然后就行了

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn=505;
struct node
{
    int x,y;
    double w;
}a[maxn*maxn];
int cot,cnt;
double ans;
int s,p;
double x[maxn],y[maxn];
int f[maxn];
int findf(int u)
{
    if(f[u]==u)
        return u;
    else
    {
        f[u]=findf(f[u]);
        return f[u];
    }
}
bool join(int u,int v)
{
    int t1=findf(u);
    int t2=findf(v);
    if(t1==t2)
    {
        return false;
    }
    else
    {
        f[t2]=t1;
        return true;
    }
}
bool cmp(node u,node v)
{
    return u.w<v.w;
}
int tt;
int main()
{
    cin>>tt;
    while(tt--)
    {
        ans=cot=cnt=0;
        cin>>s>>p;
        for(int i=1;i<=p;i++)
            cin>>x[i]>>y[i];
        for(int i=1;i<=p;i++)
        {
            for(int j=1;j<=p;j++)
            {
                if(i==j)
                    continue;
                else
                {
                    a[++cot].x=i;a[cot].y=j;a[cot].w=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                }
            }
        }
        sort(a+1,a+1+cot,cmp);
        for(int i=1;i<=p;i++)
            f[i]=i;
        if(s>0)
            s--;
        for(int i=1;i<=cot;i++)
        {
            if(cnt+s>=p-1)
                break;
            if(join(a[i].x,a[i].y))
            {
                cnt++;
                ans=a[i].w;
            }
        }
        printf("%.2f\n",ans);
    }
}

 

第八题

poj1751

这道题容易超时,尽量别用浮点数,两个之间的距离可以直接用整数

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn=800;
struct node
{
    int x,y;
    double w;
}a[maxn*maxn];
int cot,cnt;
int n,k;
int x[maxn],y[maxn];
int f[maxn];
int findf(int u)
{
    if(f[u]==u)
        return u;
    else
    {
        f[u]=findf(f[u]);
        return f[u];
    }
}
bool join(int u,int v)
{
    int t1=findf(u);
    int t2=findf(v);
    if(t1==t2)
    {
        return false;
    }
    else
    {
        f[t2]=t1;
        return true;
    }
}
bool cmp(node u,node v)
{
    return u.w<v.w;
}
int tt;
int main()
{
    int tx,ty;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&x[i],&y[i]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
    {
        if(i==j)
            continue;
        a[++cot].x=i;a[cot].y=j;a[cot].w=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
    }
    sort(a+1,a+1+cot,cmp);
    for(int i=1;i<=n;i++)
        f[i]=i;
    int tmp=0;
    scanf("%d",&k);
    for(int i=1;i<=k;i++)
    {
        scanf("%d%d",&tx,&ty);
        if(join(tx,ty))
        {
            tmp++;
        }
        join(tx,ty);
    }
    for(int i=1;i<=cot;i++)
    {
        if(tmp+cnt>=(n-1))
            break;
        if(join(a[i].x,a[i].y))
        {
            cnt++;
            printf("%d %d\n",a[i].x,a[i].y);
        }
    }
}

 

第九题:

裸最小生成树

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn=110;
struct node
{
    int x,y,w;
}a[maxn*maxn];
int cot,cnt,ans;
int n,k;
int x[maxn][maxn];
int f[maxn];
int findf(int u)
{
    if(f[u]==u)
        return u;
    else
    {
        f[u]=findf(f[u]);
        return f[u];
    }
}
bool join(int u,int v)
{
    int t1=findf(u);
    int t2=findf(v);
    if(t1==t2)
    {
        return false;
    }
    else
    {
        f[t2]=t1;
        return true;
    }
}
bool cmp(node u,node v)
{
    return u.w<v.w;
}
int tt;
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        cot=ans=cnt=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            scanf("%d",&x[i][j]);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    continue;
                a[++cot].x=i;a[cot].y=j;a[cot].w=x[i][j];
            }
        }
        sort(a+1,a+1+cot,cmp);
        for(int i=1;i<=n;i++)
            f[i]=i;
        for(int i=1;i<=cot;i++)
        {
            if(join(a[i].x,a[i].y))
            {
                cnt++;
                ans+=a[i].w;
            }
            if(cnt==n-1)
                break;
        }
        printf("%d\n",ans);
    }
}

 

第十题

最小生成树+BFS预处理

题意:就是每次到A,S就可以分其他路径

注意这题有个傻逼地方,m,n输完后,n后面跟着一串空格。。这个要自己注意,我是拿gets直接输掉了

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=100500;
struct node
{
    int num;
    int dist;
    node(int _num,int _dist):num(_num),dist(_dist){}
    friend bool operator<(node a,node b)
    {
        return a.dist>b.dist;
    }
};
struct Edge
{
    int next,to,w;
}edge[maxn];
struct Node
{
    int x,y,s;
}que[2505];
char s[550][550];
int dist[2505];
bool visit[2505];
bool vis[550][550];
int next[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int n,m,cnt,Start,End;
int head[maxn];
void add(int u,int v,int w)
{
    edge[cnt].next=head[u];edge[cnt].to=v;edge[cnt].w=w;head[u]=cnt++;
    edge[cnt].next=head[v];edge[cnt].to=u;edge[cnt].w=w;head[v]=cnt++;
}
void bfs(int st,int en)
{
    memset(vis,0,sizeof(vis));
    int tail,head;
    int tx,ty;
    tail=head=1;
    vis[st][en]=1;
    que[tail].x=st;que[tail].y=en;que[tail].s=0;
    tail++;
    while(head<tail)
    {
        for(int i=0;i<=3;i++)
        {
            tx=que[head].x+next[i][0];
            ty=que[head].y+next[i][1];
            if(tx<1||tx>n||ty<1||ty>m)
                continue;
            if(s[tx][ty]!='#'&&vis[tx][ty]==0)
            {
                que[tail].x=tx;
                que[tail].y=ty;
                que[tail].s=que[head].s+1;
                vis[tx][ty]=1;
                if(s[tx][ty]=='A'||s[tx][ty]=='S')
                    add((st-1)*m+en,(tx-1)*m+ty,que[tail].s);
                tail++;
            }
        }
        head++;
    }
}
int prime(int u)
{
    memset(dist,inf,sizeof(dist));
    memset(visit,0,sizeof(visit));
    int sum=0;
    int lowcast=0;
    priority_queue<node> q;
    dist[u]=0;
    q.push(node(u,dist[u]));
    while(!q.empty())
    {
        node x=q.top();q.pop();
        int now=x.num;
        if(visit[now]==1)
            continue;
        visit[now]=1;
        sum=sum+dist[now];
        for(int i=head[now];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(visit[v]==1)
                continue;
            if(dist[v]>edge[i].w)
            {
                dist[v]=edge[i].w;
                q.push(node(v,dist[v]));
            }
        }
    }
    return sum;
}
int main()
{
    char ss[100];
    int T;
    cin>>T;
    while(T--)
    {
        memset(head,-1,sizeof(head));cnt=0;
        cin>>m>>n;
        gets(ss);
        for(int i=1;i<=n;i++)
            gets(s[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
        {
            if(s[i][j]=='S'||s[i][j]=='A')
                bfs(i,j);
            if(s[i][j]=='S')
                Start=i,End=j;
        }
        int ans=prime((Start-1)*n+End);
        printf("%d\n",ans);
    }
}

  

 

 

第十一题

poj1679

裸次小生成树

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
const int inf=0x3f3f3f3f;
const int maxn=1005;
using namespace std;
bool visit[maxn];
int Map[maxn][maxn];
bool used[maxn][maxn];//两个点的那条边是否被使用过;
int Max[maxn][maxn];//记录MST中两个点的最大距离;
int dist[maxn];
int pre[maxn];//保存父节点;
int n,m;
int prime()
{
    int ans=0;
    memset(visit,false,sizeof(visit));
    memset(Max,0,sizeof(Max));
    memset(used,0,sizeof(used));
    visit[1]=1;pre[1]=-1;
    for(int i=2;i<=n;i++)
    {
        dist[i]=Map[1][i];
        pre[i]=1;
    }
    dist[1]=0;
    for(int i=1;i<=n-1;i++)
    {
        int lowcast=inf;
        int temp=-1;
        for(int j=1;j<=n;j++)
        {
            if(!visit[j]&&lowcast>dist[j])
            {
                lowcast=dist[j];
                temp=j;
            }
        }
        if(lowcast==inf)//这说明有点不连通;
            return -1;
        ans+=lowcast;//最小生成树的值;
        visit[temp]=1;
        used[temp][pre[temp]]=used[pre[temp]][temp]=1;
        for(int j=1;j<=n;j++)
        {
            if(visit[j])
                Max[j][temp]=Max[temp][j]=max(Max[j][pre[temp]],dist[temp]);//数组的作用是记录MST里面两个点的最大距离;
            if(!visit[j]&&dist[j]>Map[temp][j])
            {
                dist[j]=Map[temp][j];
                pre[j]=temp;
            }
        }
    }
    return ans;
}
int ans;
int SMST()
{
    int minn=inf;
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(Map[i][j]!=inf&&(!used[i][j]))
            {
                minn=min(minn,ans+Map[i][j]-Max[i][j]);
            }
        }
    }
    if(minn==inf)
        return -1;//没有最小生成树;
    return minn;
}
int main()
{
    int t;
    int x,y,w;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
        {
            if(i==j)
                Map[i][j]=0;
            else
                Map[i][j]=inf;
        }
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y>>w;
            Map[x][y]=w;Map[y][x]=w;
        }
        ans=prime();
        if(ans==-1)
        {
            printf("Not Unique!\n");
            continue;
        }
        if(ans==SMST())printf("Not Unique!\n");
        else printf("%d\n",ans);

    }
    return 0;
}

  

 

第十二题

hdu1233

裸最小生成树

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
#define maxn 1005000
using namespace std;
struct node
{
    int num;
    int dist;
    node(int _num=0,int _dist=0):num(_num),dist(_dist){}
    friend bool operator<(node a,node b)
    {
        if(a.dist==b.dist)
            return a.num>b.num;
        return a.dist>b.dist;
    }
};
struct Edge
{
    int next;
    int to;
    int w;
}edge[maxn];
int dist[100500];
int cnt;
int head[maxn];
int visit[100500];
void add(int u,int v,int w)
{
    edge[cnt].next=head[u];edge[cnt].w=w;
    edge[cnt].to=v;head[u]=cnt++;
}
int prime(int u)
{
    memset(dist,inf,sizeof(dist));
    memset(visit,0,sizeof(visit));
    int sum=0;
    int lowcast=0;
    priority_queue<node> q;
    dist[u]=0;
    q.push(node(u,dist[u]));
    while(!q.empty())
    {
        node x=q.top();q.pop();
        int now=x.num;
        if(visit[now]==1)
            continue;
        visit[now]=1;
        sum=sum+dist[now];
        for(int i=head[now];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(visit[v]==1)
                continue;
            if(dist[v]>edge[i].w)
            {
                dist[v]=edge[i].w;
                q.push(node(v,dist[v]));
            }
        }
    }
    return sum;
}
int main()
{
    int n,m;
    int x,y,w;
    while(scanf("%d",&n)&&n)
    {
        m=n*(n-1)/2;
        memset(head,-1,sizeof(head));cnt=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w);add(y,x,w);
        }
    int ans=prime(1);
    printf("%d\n",ans);
    }
}

 

 

第十三题

好像和前面一样的,所以没写

 

 

第十四题

#include<iostream>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<cstdio>
const int inf=0x7fffffff;
using namespace std;
struct node
{
    double x;
    double y;
}a[105];
int n;
double Map[105][105];
double dist[105];
bool visit[105];
int flag;
double prime(int x)
{
    memset(visit,0,sizeof(visit));
    flag=0;
    int temp=inf;
    double lowcast;
    double sum=0;
    for(int i=1;i<=n;i++)
        dist[i]=Map[x][i];
    visit[x]=1;
    for(int i=1;i<=n-1;i++)
    {
        lowcast=inf;
        for(int j=1;j<=n;j++)
        {
            if(visit[j]==0&&dist[j]<lowcast)
            {
                temp=j;lowcast=dist[j];
            }
        }
        if(temp==inf)
        {
            flag=1;break;
        }
        visit[temp]=1;
        sum+=lowcast;
        if(dist[temp]>1000)
            flag=1;
        for(int k=1;k<=n;k++)
        {
            if(visit[k]==0&&dist[k]>Map[temp][k])
                dist[k]=Map[temp][k];
        }
    }
    return sum;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&a[i].x,&a[i].y);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    Map[i][j]=0;
                else
                    Map[i][j]=inf;
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                Map[i][j]=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
                Map[j][i]=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
                if(Map[i][j]>1000||Map[i][j]<10)
                {
                    Map[i][j]=inf;
                    Map[j][i]=inf;
                }
            }
        }
        double x=prime(1);
        if(flag==1||x>=inf)
            printf("oh!\n");
        else
            {
                x=x*100;
                printf("%.1lf\n",x);
            }
    }
    return 0;
}

 

  

 

posted @ 2018-11-16 21:14  荒岛的龟  阅读(338)  评论(0编辑  收藏  举报