zoukankan      html  css  js  c++  java
  • POJ

    An earthquake takes place in Southeast Asia. The ACM (Asia Cooperated Medical team) have set up a wireless network with the lap computers, but an unexpected aftershock attacked, all computers in the network were all broken. The computers are repaired one by one, and the network gradually began to work again. Because of the hardware restricts, each computer can only directly communicate with the computers that are not farther than d meters from it. But every computer can be regarded as the intermediary of the communication between two other computers, that is to say computer A and computer B can communicate if computer A and computer B can communicate directly or there is a computer C that can communicate with both A and B.

    In the process of repairing the network, workers can take two kinds of operations at every moment, repairing a computer, or testing if two computers can communicate. Your job is to answer all the testing operations.
    Input
    The first line contains two integers N and d (1 <= N <= 1001, 0 <= d <= 20000). Here N is the number of computers, which are numbered from 1 to N, and D is the maximum distance two computers can communicate directly. In the next N lines, each contains two integers xi, yi (0 <= xi, yi <= 10000), which is the coordinate of N computers. From the (N+1)-th line to the end of input, there are operations, which are carried out one by one. Each line contains an operation in one of following two formats:
    1. “O p” (1 <= p <= N), which means repairing computer p.
    2. “S p q” (1 <= p, q <= N), which means testing whether computer p and q can communicate.

    The input will not exceed 300000 lines.
    Output
    For each Testing operation, print “SUCCESS” if the two computers can communicate, or “FAIL” if not.
    Sample Input
    4 1
    0 1
    0 2
    0 3
    0 4
    O 1
    O 2
    O 4
    S 1 4
    O 3
    S 1 4
    Sample Output
    FAIL
    SUCCESS

    题意:有N台电脑一开始全是坏掉的,用O 操作修复第i台电脑,用S操作检查x和y号电脑是否互联,其中两台好的电脑如果距离小于D则可以互联,每台电脑的标号是他输入时的下标,现在输入所有电脑的坐标,查询两两电脑之间是否可以直接或间接互联

    一开始看到坐标以为是图论,后来发现因为电脑之间可以间接联通,因此能够在一定距离内修好并连同的电脑可以作为一个桥梁使附近剩下的电脑尽肯能的联通,因此是类似于并查集中收揽集合的过程,而检查是否互联也可以用并查集中find函数实现。

    首先输入所有电脑的坐标,并计算两两之间的建立,如果两两距离小于D还能继续将其列入可能互联的待选列表中(vector)

    然后修电脑的操作将电脑修好的标记标为true,并通过之前的待选列表将刚修好的电脑尽可能的利用并查集的join函数与其他电脑互联。

    查询时只需check两两电脑是否在同一个集合中即可判断是否互联

    #include<stdio.h>///并查集
    #include<set>
    #include<math.h>
    #include<string>
    #include<string.h>
    #include<iostream>
    #include<queue>
    #include<vector>
    #define LL long long
    using namespace std;
    struct com
    {
        double x,y;
    } a[1004];
    int n,t,ans,d,tmp;
    double dis[1005][1008];
    vector<int>v[1005];
    bool vis[1005];
    int x,y;
    int zz[1005];
    int finds(int x)
    {
        int r=x,t;
        while(r!=zz[r])
        {
            t=r;
            r=zz[r];
            zz[t]=zz[r];
        }
        return r;
    }
    void join(int a,int b)
    {
        int fa=finds(a),fb=finds(b);
        if(fa!=fb)
        {
            zz[fa]=fb;
        }
    }
    int main()
    {
        while(scanf("%d%d",&n,&d)!=EOF)
        {
            memset(vis,false,sizeof(vis));
            memset(dis,0x3f,sizeof(dis));
            for(int i=1;i<=n;i++)v[i].clear();
            for(int i=1;i<=n;i++)zz[i]=i;
            for(int i=1; i<=n; i++)
            {
                scanf("%lf%lf",&a[i].x,&a[i].y);
                for(int j=1; j<i; j++)
                {
                    dis[i][j]=dis[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(dis[i][j]<=d)///将每个电脑周围的可选距离的电脑收入vector中待选
                    {
                        v[i].push_back(j);
                        v[j].push_back(i);
                    }
                }
            }
            char flag[3];
            while(scanf("%s",flag)!=EOF)
            {
                if(flag[0]=='O')
                {
                    scanf("%d",&tmp);
                    vis[tmp]=true;
                    for(int i=0; i<v[tmp].size(); i++)
                    {
                        if(vis[v[tmp][i]])
                        {
    //                        printf("%d-------%d
    ",vis[v[tmp][i]],v[tmp][i]);
                            join(v[tmp][i],tmp);
                        }
                    }
    //                for(int i=1;i<=n;i++)
    //                {
    //                    printf("%d====>%d
    ",i,zz[i]);
    //                }
                }
                else
                {
                    scanf("%d%d",&x,&y);
                    if(finds(x)==finds(y))
                    {
                        printf("SUCCESS
    ");
                    }
                    else
                    {
                        printf("FAIL
    ");
                    }
                }
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    数据结构与算法----双向链表
    数据结构与算法----数学应用之一元多项式
    数据结构----线性表顺序和链式结构的使用(c)
    Android--Otto事件总线 -- 组件之间通讯框架使用 --模式解析
    递归 —— 二分查找法 —— 归并排序
    自己做悬浮拖拽按钮依赖
    RePlugin 插件化-内置加载
    Android图片处理--缩放
    数据结构与算法---常用三大排序算法
    Android图片处理--全景查看效果
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135832.html
Copyright © 2011-2022 走看看