HDU

来源:互联网 发布:java计算天干地支 编辑:程序博客网 时间:2024/05/22 06:13

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1875

题意:中文题0.0

思路:先连接每条边,再kruskal一下,如果加入边的权值<10或>1000,就不连接,否则就连接并计数t。如果t==n-1,即等于需要连接的边数,那么就代表可以连接,否则不行


代码:

#include <cstdio>#include <cmath>#include <iostream>#include <cstring>#include <algorithm>#include <queue>#include <stack>#include <vector>#include <map>#include <numeric>#include <set>#include <string>#include <cctype>#include <sstream>#define INF 0x3f3f3f3fusing namespace std;typedef long long LL;typedef pair<int, int> P;const int maxn = 5e5 + 5;int n,p[105],cnt,t;struct point{    int x,y;}po[maxn];struct edge{    int u,v;    double cost;}e[maxn];bool cmp(edge a,edge b){    return a.cost<b.cost;}void init (int n) {for (int i=0;i<=n;i++) p[i]=i;}int Find(int x) {return p[x]==x?x: ( p[x]=Find ( p[x] ) );}bool same(int a,int b) {return Find(a)==Find(b);}void unite (int x,int y){    x=Find(x);    y=Find(y);    if (x!=y)  p[x]=y;}double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}double kruskal(){    sort(e,e+cnt,cmp);    double ans=0;    int t=0;    for (int i=0;i<cnt;i++){        edge ee=e[i];        if (!same(ee.u,ee.v)){            if (ee.cost<10||ee.cost>1000) continue;            unite(ee.u,ee.v);            ans+=ee.cost*100;            t++;        }    }    if (t==n-1) return ans;    else return -1;}int main () {    //freopen ("in.txt", "r", stdin);    scanf ("%d",&t);    while (t--){        scanf ("%d",&n);        init(n);        for (int i=1;i<=n;i++){            scanf ("%d%d",&po[i].x,&po[i].y);        }        cnt=0;        for (int i=1;i<=n;i++){            for (int j=i+1;j<=n;j++){                e[cnt].u=i;                e[cnt].v=j;                e[cnt++].cost=dis(po[i],po[j]);            }        }        double ans=kruskal();        if (ans!=-1) printf ("%.1f\n",ans);        else printf ("oh!\n");    }    return 0;}


原创粉丝点击