hdu 1829  A Bug's Life

题目大意: 给你n个动物,输入m行a,b,表示a和b应该是异性的,要你判断是否有同性恋。

并查集中,1到n代表应性别,n+1到2n代表一个性别,合并一下,判断一下就好。

 #include <cstdio>
 #include <map>
 #include <queue>
 #include <cstring>
 #include <algorithm>
 #include <iostream>
 using namespace std;
 #define mem0(x) memset(x,0,sizeof(x))
 #define mem1(x) memset(x,-1,sizeof(x))
 typedef long long LL;
 const int INF = 0x3f3f3f3f;
  + ;

 ];

 void init(int n)
 {
     ;i<=n*;i++)
         pa[i] = i;
 }

 int uf_find(int x){return x == pa[x] ? x : (pa[x] = uf_find(pa[x]));}
 bool same(int x,int y){return uf_find(x) == uf_find(y);}

 void join(int x,int y)
 {
     int fx = uf_find(x);int fy = uf_find(y);
     if(fx != fy)
         pa[fx] = fy;
 }

 int main()
 {
     ;
     scanf("%d",&t);
     while(t--)
     {
         scanf("%d%d",&n,&m);
         init(n);
         ;
         ;i<m;i++)
         {
             scanf("%d%d",&x,&y);
             if(same(x,y) || same(x+n,y+n))
                 flag = ;
             else
                 join(x,y+n);join(x+n,y);
         }
         printf("Scenario #%d:\n",p++);
         if(flag)
             printf("No suspicious bugs found!\n");
         else
             printf("Suspicious bugs found!\n");
         puts("");
     }
     ;
 }

hdu 1856  More is better

题目大意:合并一系列关系之后,问你,结点最多的那堆,有多少个结点,即 最大连通量的结点个数。

用一个sum数组就能解决问题了。

 #include <cstdio>
 #include <map>
 #include <queue>
 #include <cstring>
 #include <algorithm>
 #include <iostream>
 using namespace std;
 #define mem0(x) memset(x,0,sizeof(x))
 #define mem1(x) memset(x,-1,sizeof(x))
 typedef long long LL;
 const int INF = 0x3f3f3f3f;

  + ;
 int pa[maxn];
 int sum[maxn];
 void init()
 {
     ;i<=maxn;i++)
         pa[i] = i,sum[i] = ;
 }

 int uf_find(int x){return x == pa[x] ? x : (pa[x] = uf_find(pa[x]));}
 bool same(int x,int y){return uf_find(x) == uf_find(y);}

 void join(int x,int y)
 {
     int fx = uf_find(x);int fy = uf_find(y);
     if(fx == fy) return ;
     if(sum[fy] > sum[fx])
     {

         pa[fx] = fy;
         sum[fy] = sum[fy] + sum[fx];
     }
     else
     {
         pa[fy] = fx;
         sum[fx] = sum[fx] + sum[fy];
     }

 }
 int main()
 {
     int n,x,y;
     while(~scanf("%d",&n))
     {
         init();
         ;i<n;i++)
         {
             scanf("%d%d",&x,&y);
             join(x,y);
         }
          ;
         ;i<=maxn;i++)
             ans = max(ans,sum[i]);
         printf("%d\n",ans);

     }
     ;
 }

hdu 2473  Junk-Mail Filter(并查集的删除操作,虚拟父结点)

把1到n的父结点设为n+1到2n,即pa[i] = n + i;

n+1到2n+m按平常并查集的初始化。2n+1到2n+m的结点的设立的目的如代码所示。

删除的结点把他们的父结点从n+i指向cnt++。

注意一下pa数组要开2n+m大小。

 #include <cstdio>
 #include <map>
 #include <set>
 #include <queue>
 #include <cstring>
 #include <algorithm>
 #include <iostream>
 using namespace std;
 typedef long long LL;
 const int INF = 0x3f3f3f3f;
 #define mem0(x) memset(x,0,sizeof(x))
 #define mem1(x) memset(x,-1,sizeof(x))

 ;//数组要开 2*n+m

 char ch;
 int n,m,x,y,cnt,ans;
 int pa[maxn];

 void init(int n,int m)
 {
     cnt =  * n;
     ;i<n;i++)
         pa[i] = i + n;
     *n+m;i++)
         pa[i] = i;
 }

 int uf_find(int x){return x == pa[x] ? x : (pa[x] = uf_find(pa[x]));}

 void join(int x,int y)
 {
     int fx = uf_find(x);int fy = uf_find(y);
     if(fx != fy)
         pa[fx] = fy;
 }

 int main()
 {
     ;
     while(~scanf("%d%d",&n,&m))
     {
          && m == )    break;
         init(n,m);
         ;i<m;i++)
         {
             getchar();
             scanf("%c",&ch);
             if(ch == 'M')
                 scanf("%d%d",&x,&y),join(x,y);
             else if(ch == 'S')
                 scanf("%d",&x),pa[x] = cnt++;
         }

         set<int>s;
         ;i<n;i++)
             s.insert(uf_find(i));

         printf("Case #%d: %d\n",p++,s.size());
     }
     ;
 }

hdu 3038  How Many Answers Are Wrong(带权并查集)

题目大意:一行给出三个整数 x y sum 代表从x到y这段 数值之和为sum,让你判断

怎么用并查集来做呢?转换成前缀和。

rrank[i] 代表着 i到它父结点之间所有结点的和。

if(fx == fy)
        return ((rrank[y] - rrank[x]) == sum) ? true :false;
    pa[fy] = fx;
    rrank[fy] = rrank[x] - rrank[y] + sum;
    return true;

高亮的代码,可以由rrank[fy] = rrank[x] - rrank[y] + sum;这个等式可以自己画个条条,摸索一下。rrank[x]代表x到fx的和,rrank[y]代表y到fy的和,rrank[x]+sum就代表了y到fx的和,那么

rrank[fy](我们的目的是把rrank[fy]更新成fy到fx的和)就是y到fx的和减掉y到fy的距离,即rrank[x]+sum再减掉rrank[y]

if(x == pa[x]) return x;
    int fa = pa[x];
    pa[x] = uf_find(pa[x]);
rrank[x] += rrank[fa];
return pa[x];

高亮的两句话的顺序弄清楚为什么,谁先谁后,就能对这道题的解决思路有了很清晰的了解,这是非常关键的部分。同时也是对递归的一个更深刻的理解。23333我一开始还纳闷怎么是这个顺序后来才想明白。

 #include <cstdio>
 #include <algorithm>
 using namespace std;
 typedef long long LL;
 const int INF = 0x3f3f3f3f;

 ;
 int pa[maxn],rrank[maxn];
 void init(int n)
 {
     ;i<=n;i++)
         pa[i] = i,rrank[i] = ;
 }

 int uf_find(int x)
 {
     if(x == pa[x]) return x;
     int fa = pa[x];
     pa[x] = uf_find(pa[x]);
     rrank[x] += rrank[fa];
     return pa[x];
 }

 bool join(int x,int y,int sum)
 {
     int fx = uf_find(x);int fy = uf_find(y);

     if(fx == fy)
         return ((rrank[y] - rrank[x]) == sum) ? true :false;
     pa[fy] = fx;
     rrank[fy] = rrank[x] - rrank[y] + sum;//rrank[fy] + rrank[y] = rrank[x] + sum 画个图就出来了
     return true;
 }

 int main()
 {
     int n,m;
     while(~scanf("%d%d",&n,&m))
     {
         init(n);
         ;
         ;i<m;i++)
         {
             scanf("%d%d%d",&x,&y,&sum);
             ,y,sum) )  ans++;
         }
         printf("%d\n",ans);
     }
     ;
 }

hdu 并查集分类(待续)的更多相关文章

  1. CCCC L2-010. 排座位【并查集/分类讨论】

    L2-010. 排座位 时间限制 150 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位. ...

  2. 【BZOJ-2503】相框 并查集 + 分类讨论

    2503: 相框 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 71  Solved: 31[Submit][Status][Discuss] Desc ...

  3. hdu 3635 Dragon Balls(并查集应用)

    Problem Description Five hundred years later, the number of dragon balls will increase unexpectedly, ...

  4. HDU1198水管并查集Farm Irrigation

    Benny has a spacious farm land to irrigate. The farm land is a rectangle, and is divided into a lot ...

  5. poj1417 true liars(并查集 + DP)详解

    这个题做了两天了.首先用并查集分类是明白的, 不过判断是否情况唯一刚开始用的是搜索.总是超时. 后来看别人的结题报告, 才恍然大悟判断唯一得用DP. 题目大意: 一共有p1+p2个人,分成两组,一组p ...

  6. HDU 1272 小希的迷宫(并查集) 分类: 并查集 2015-07-07 23:38 2人阅读 评论(0) 收藏

    Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就 ...

  7. HDU 2473 Junk-Mail Filter 并查集删除(FZU 2155盟国)

    http://acm.hdu.edu.cn/showproblem.php?pid=2473 http://acm.fzu.edu.cn/problem.php?pid=2155 题目大意: 编号0~ ...

  8. hdu 5652 India and China Origins 并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5652 题目大意:n*m的矩阵上,0为平原,1为山.q个询问,第i个询问给定坐标xi,yi,表示i年后这 ...

  9. HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...

随机推荐

  1. nyoj_31

    题目描述:五个数求最值. #include <iostream> #include <algorithm> using namespace std; int main(){ ] ...

  2. Divide and conquer:4 Values whose Sum is 0(POJ 2785)

    找四个数的和为0 题目大意:给定四个集合,要你每个集合选4个数字,组成和为0 这题是3977的简单版,只要和是0就可以了 #include <iostream> #include < ...

  3. WebService及WCF获取客户端IP,端口

    wcf获取客户端IP,端口 var context = OperationContext.Current; var properties = context.IncomingMessageProper ...

  4. 【编程题目】一个整数数组,长度为 n,将其分为 m 份,使各份的和相等,求 m 的最大值★★ (自己没有做出来!!)

    45.雅虎(运算.矩阵): 2.一个整数数组,长度为 n,将其分为 m 份,使各份的和相等,求 m 的最大值 比如{3,2,4,3,6} 可以分成 {3,2,4,3,6} m=1; {3,6}{2,4 ...

  5. 配置TFS2010的用户截图

    先要添加一个管理用户

  6. 如何用Endnote导入你要用的格式

    在Google搜索某一个期刊名 ens格式的文件,下载,然后放入endnote的文件夹中(C:\Program Files (x86)\EndNote X7\Styles) 然后将其导入即可

  7. 模拟赛1101d2

    幸运数字(number)Time Limit:1000ms Memory Limit:64MB题目描述LYK 最近运气很差,例如在 NOIP 初赛中仅仅考了 90 分,刚刚卡进复赛,于是它决定使用一些 ...

  8. Linux 压缩系列常用命令

    tar 命令: http://man.linuxde.net/tar zip 命令: http://man.linuxde.net/zip unzip 命令: http://man.linuxde.n ...

  9. js对象

    js中除数字.字符串.布尔值.null值.undefined之外都是对象. 对象是属性的容器,属性包含属性名和值,属性名可以是包括空字符串在内的任意字符串(个人想法还是使用js标识符好,省的麻烦),值 ...

  10. php常用判断的函数

    empty($var)        //用来检查变量是否为空(没有值或零值) isset($var)           //这个//测试一个变量看它是否已被定义. gettype($var)   ...