zoukankan      html  css  js  c++  java
  • poj-2236 Wireless Network &&poj-1611 The Suspects && poj-2524 Ubiquitous Religions (基础并查集)

    http://poj.org/problem?id=2236

    由于发生了地震,有关组织组把一圈电脑一个无线网,但是由于余震的破坏,所有的电脑都被损坏,随着电脑一个个被修好,无线网也逐步恢复工作,但是由于硬件的限制,一台电脑和另一台电脑能够相连当他们之间的距离小于d,或者还有一台电脑当中介,分别与两台电脑相连。

    在修复的过程中,工作者会有两种操作,修复电脑和询问电脑a和电脑b是否相连。当询问的时候输出答案。

    因为输入数据很大,需要快速判断电脑a和电脑b相连,所以自然想到用并查集。

    初始时候 全部电脑都是损坏的,那么每修复一次,就需要把与当前电脑距离小于d并且已经修复的电脑连接起来,询问的时候直接判断即可。

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn = 1010;
     6 struct node
     7 {
     8     int x,y;
     9 }p[maxn];
    10 int par[maxn],flag[maxn];  //作为是否修复的标记
    11 int n;
    12 double dis[maxn][maxn];  //存储两点之间的距离
    13 double d;
    14 void init()
    15 {
    16     for(int i=1;i<=n;i++) par[i]=i;
    17 }
    18 
    19 int find(int x)
    20 {
    21     return x==par[x]?x:par[x]=find(par[x]);
    22 }
    23 
    24 void unite(int x,int y)
    25 {
    26     x=find(x);
    27     y=find(y);
    28     if(x!=y)
    29         par[x]=y;
    30 }
    31 
    32 void distance(int a,int b)
    33 {
    34     dis[a][b]=dis[b][a]=sqrt(1.0*(p[a].x-p[b].x)*(p[a].x-p[b].x)+1.0*(p[a].y-p[b].y)*(p[a].y-p[b].y));
    35 }
    36 
    37 void solve(int x)
    38 {
    39     for(int i=1;i<=n;i++)
    40     {
    41         if(i!=x&&flag[i]&&dis[x][i]<=d)
    42             unite(x,i);
    43     }
    44 }
    45 
    46 int main()
    47 {
    48    //freopen("a.txt","r",stdin);
    49     scanf("%d%lf",&n,&d);
    50     init();
    51     memset(flag,0,sizeof(flag));
    52     memset(dis,0,sizeof(dis));
    53     for(int i=1;i<=n;i++)
    54         scanf("%d%d",&p[i].x,&p[i].y);
    55     for(int i=1;i<=n;i++)   //预处理所有两点之间的距离
    56         for(int j=i+1;j<=n;j++)
    57         distance(i,j);
    58     char s[2];
    59     int a,b;
    60     while(~scanf("%s",s))
    61     {
    62         if(s[0]=='O')
    63         {
    64             scanf("%d",&a);
    65             flag[a]=1;
    66             solve(a);
    67         }
    68         else if(s[0]=='S')
    69         {
    70             scanf("%d%d",&a,&b);
    71             if(find(a)==find(b)) printf("SUCCESS
    ");
    72             else printf("FAIL
    ");
    73         }
    74     }
    75     return 0;
    76 }

     http://poj.org/problem?id=1611

     在大学里有n个学生(0-n-1)和m个社团,每个学生可以加多个社团,但是因为SARS的流行,学校需要统计出有多少病毒携带者,如果一个社团有一个携带者,那么整个社团都是  病毒携带者,现在已知0号学生是携带者,给出m个社团的信息,求出有多少人感染。

     基础的并查集,只要增加一个rank[]用来统计每一个组的人数,这样在unite的时候累加合并过来的人数,最后输出0号所在的组的人数。

     1 #include <cstdio>
     2 #include <queue>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 const int maxn = 30010;
     7 int par[maxn],rank[maxn];
     8 
     9 void init(int n)
    10 {
    11     for(int i=0;i<n;i++)
    12     {
    13         par[i]=i;
    14         rank[i]=1;
    15     }
    16 }
    17 
    18 int find(int x)
    19 {
    20     return x==par[x]?x:par[x]=find(par[x]);
    21 }
    22 
    23 void unite(int x,int y)
    24 {
    25     x=find(x);
    26     y=find(y);
    27     if(x!=y)
    28     {
    29         par[x]=y;
    30         rank[y]+=rank[x];
    31     }
    32 }
    33 
    34 int main()
    35 {
    36     int n,m,k,a,b;
    37     while(~scanf("%d%d",&n,&m))
    38     {
    39         if(n==0&&m==0) break;
    40         init(n);
    41         for(int i=0;i<m;i++)
    42         {
    43             scanf("%d",&k);
    44             for(int j=0;j<k;j++)
    45             {
    46                 scanf("%d",&a);
    47                 if(j==0)
    48                 {
    49                     b=a;
    50                 }
    51                 else unite(a,b);
    52             }
    53         }
    54         printf("%d
    ",rank[find(0)]);
    55     }
    56     return 0;
    57 }

    http://poj.org/problem?id=2524

    n个学生,每个学生都只有一种信仰,给出m条关系,统计最多有多少种信仰。

    简单并查集,读入关系后合并即可。

     1 #include <cstdio>
     2 const int maxn = 50010;
     3 int n,count,par[maxn];
     4 
     5 void init(int n)
     6 {
     7     for(int i=1;i<=n;i++)
     8     {
     9         par[i]=i;
    10     }
    11 }
    12 
    13 int find(int x)
    14 {
    15     return x==par[x]?x:par[x]=find(par[x]);
    16 }
    17 
    18 void unite(int x,int y)
    19 {
    20     x=find(x);
    21     y=find(y);
    22     if(x!=y)
    23     {
    24         par[x]=y;
    25         count--;
    26     }
    27 }
    28 
    29 int main()
    30 {
    31     int m,a,b,j=1;
    32     while(~scanf("%d%d",&n,&m))
    33     {
    34         if(n==0&&m==0) break;
    35         count=n;
    36         init(n);
    37         for(int i=0;i<m;i++)
    38         {
    39             scanf("%d%d",&a,&b);
    40             unite(a,b);
    41         }
    42         printf("Case %d: %d
    ",j++,count);
    43     }
    44     return 0;
    45 }
  • 相关阅读:
    Spring总结(三)
    lucene全文检索
    知识点
    postman本地测试post接口
    第一份任务,写接口验证接口写文档
    spring Date JPA的主要编程接口
    springmvc之格式化要显示的小数或者日期。
    限制action所接受的请求方式或请求参数
    正则表达式映射
    Url通配符映射
  • 原文地址:https://www.cnblogs.com/nowandforever/p/4486080.html
Copyright © 2011-2022 走看看