zoukankan      html  css  js  c++  java
  • [HDU 1272] 小希的迷宫

    小希的迷宫

    Time Limit: 2000/1000 MS (Java/Others)    

    Memory Limit: 65536/32768 K (Java/Others)

    Problem Description
    上次Gardon的迷宫城堡小希玩了很久,现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。 
    Input
    输入包含多组数据,每组数据是一个以0 0结尾的整数对列表,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。每两组数据之间有一个空行。 
    整个文件以两个-1结尾。
    Output
    对于输入的每一组数据,输出仅包括一行。如果该迷宫符合小希的思路,那么输出"Yes",否则输出"No"。
    Sample Input
    6 8
    5 3
    5 2
    6 4
    5 6
    0 0
     
    8 1
    7 3
    6 2
    8 9
    7 5
    7 4
    7 8
    7 6
    0 0
     
    3 8
    6 8
    6 4
    5 3
    5 6
    5 2
    0 0
     
    -1 -1
    Sample Output
    Yes
    Yes
    No
     
    【题解】
    其实这道题就是运用并查集来判断是否存在环且是否全图为连通图。
    判断是否存在环就是在join的时候判断如果已经join过了,那么就有环了,输出false。
    判断全图为连通图就是找根节点,如果只有一个,那么就是联通的。
    代码实现如下:
    时间复杂度 O(Tk) (T为数据组数,k为有多少条边)
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int pre[100001],r[100001];
     4 bool vis[100001];
     5 bool flag=0;
     6 int findset(int x) {
     7     int r=x;
     8     while(pre[r]!=r) r=pre[r];
     9     int i=x,j;
    10     while(i!=r) {
    11         j=pre[i];
    12         pre[i]=r;
    13         i=j;
    14     }
    15     return r;
    16 }
    17 void join(int f1,int f2) {
    18     if(r[f1]<=r[f2]) {
    19         pre[f1]=f2;
    20         if (r[f1]==r[f2]) r[f2]++;
    21     }
    22     else pre[f2]=f1;
    23 }
    24 int main() {
    25     int a,b;
    26     while(~scanf("%d%d",&a,&b)) {
    27         for (int i=1;i<=100000;++i) pre[i]=i,r[i]=1;
    28         memset(vis,0,sizeof(vis));
    29         if (a==-1&&b==-1) break;
    30         if (a==0&&b==0) {
    31             printf("Yes
    ");
    32             continue;
    33         }
    34         int sign=0,minn=1000001,maxn=-1;
    35         do {
    36             minn=min(min(minn,a),b);
    37             maxn=max(max(maxn,a),b);
    38             vis[a]=vis[b]=1;
    39             int f1=findset(a),f2=findset(b);
    40             if(f1==f2) sign=-1;
    41             else join(f1,f2);
    42             scanf("%d%d",&a,&b);
    43             if(a==0&&b==0) break;
    44         }while(1);
    45         if(sign==-1) {
    46             printf("No
    ");
    47             continue;
    48         }
    49         bool x=0;
    50         for (; minn<=maxn; minn++)
    51             if(vis[minn] && pre[minn]==minn) {
    52                 if(x==1) {x=0;break;}
    53                 else x=1;
    54             }
    55         if(x) printf("Yes
    ");
    56         else printf("No
    ");
    57     }
    58     return 0;
    59 }
    View Code
    这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
  • 相关阅读:
    Torchkeras,一个源码不足300行的深度学习框架
    【知乎】语义分割该如何走下去?
    【SDOI2017】天才黑客(前后缀优化建图 & 最短路)
    【WC2014】紫荆花之恋(替罪羊重构点分树 & 平衡树)
    【SDOI2017】相关分析(线段树)
    【学习笔记】分治法最短路小结
    【CH 弱省互测 Round #1 】OVOO(可持久化可并堆)
    【学习笔记】K 短路问题详解
    【学习笔记】浅析平衡树套线段树 & 带插入区间K小值
    【APIO2020】交换城市(Kruskal重构树)
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/hdu1272.html
Copyright © 2011-2022 走看看