zoukankan      html  css  js  c++  java
  • 南阳1022——合纵连横(并、查、删)

    题目:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=1022

    想法:比 亲戚这一题难,因为还涉及到 退出 即 解除关系 问题,除了find()、combine()函数还新加一个删除delet()函数。

    人(诸侯国)先坐在箱子里,然后连箱子,最后某个人要退出时,直接从箱子里出来,坐到新的箱子里去(删),这样,之前如果有许多其他的人连在要退出的人身上,其他人的关系依然在,因为箱子还在

    注意:第一次runtime error  ,提示到:数组开得太小了,导致访问到了不该访问的内存区域;我就将max=100005扩大到max=1000005,结果就过了,但不知道为什么数组要开这么大?

    代码:

     1 #include<stdio.h>
     2 #include<memory.h>
     3 #define max 1000005
     4 int f[2*max],box[2*max],mark[max];//f[x]=a指 标号为x的箱子 连接到标号为a的箱子,box[x]=i,x这个人坐在标号为i的箱子里,mark[i]记录i是否为根源
     5 //
     6 int find(int a) //查,查a连接在哪个上面
     7 {
     8     if(f[a]!=a)//说明还没有找到最上面的箱子(就是f[a]==a的箱子,f[a]==a表示的是a钩在a上,即发散的根源了)
     9         f[a]=find(f[a]);//查询并压缩
    10     return f[a];
    11 }
    12 //
    13 void combine(int x,int y) //并,将标号为x,y的箱子连接
    14 {
    15     int a,b;
    16     a=find(x);
    17     b=find(y);
    18     if(a!=b)//两箱子连接的根源箱子不一样
    19         f[a]=b;//让两者的根相连,避免有些箱子丢掉了根,去连别人了
    20     else return;
    21 }
    22 //
    23 void delet(int i,int k) //删除i人,重新拿一个没用过的箱子来,标号为k
    24 {
    25     box[i]=k;//将i这个人放在 标号为k的箱子里
    26     f[k]=k;//这个箱子钩在自己身上
    27     return;
    28 }
    29 int main()
    30 {
    31     char ch;
    32     int a,b,i,n,m,k,c=0,sum;
    33     while(~scanf("%d %d",&n,&m)) //n个国家,m种操作
    34     {
    35         //初始化
    36         sum=0;
    37        memset(mark,0,sizeof(mark));
    38         for(i=0; i<n; i++)
    39         {
    40             box[i]=i;//i这个人,坐在编号为i的box里
    41             f[i]=i;//box[i]这个箱子连在标号为i的箱子上
    42         }
    43         k=n;//新的box的下标(之前初始化用到了n-1)
    44         //输入
    45         for(i=0; i<m; i++)
    46         {
    47             getchar();//将上一行的'
    '去掉
    48             scanf("%c",&ch);
    49             if(ch=='U') //合并
    50             {
    51                 scanf("%d %d",&a,&b);
    52                 combine(box[a],box[b]);
    53             }
    54             if(ch=='D')  //退出
    55             {
    56                 scanf("%d",&a);//a退出
    57                 delet(a,k);
    58                 k++;
    59             }
    60         }
    61 
    62         //求共有几个集合
    63         for(i=0; i<n; i++)
    64         {
    65             a=find(box[i]);
    66             if(!mark[a]) //说明它是新的根
    67             {
    68                 mark[a]=1;//a这个根已经产生了,标记一下
    69                 sum++;
    70             }
    71         }
    72         printf("Case #%d: %d
    ",++c,sum);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    C#按模板生成word文档总结
    Aspose.Words.dll根据模板生成word
    WCF服务
    Fiddler抓包工具
    文本过长显示...
    java JDK 环境变量配置
    js return关键字
    js限制文本框输入内容
    jQuery学习一
    JSON 教程
  • 原文地址:https://www.cnblogs.com/li-yaoyao/p/9525105.html
Copyright © 2011-2022 走看看