码迷,mamicode.com
首页 > 其他好文 > 详细

南阳1022——合纵连横(并、查、删)

时间:2018-08-23 19:23:50      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:case   memory   error   etc   想法   去掉   div   就是   scanf   

题目: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();//将上一行的‘\n‘去掉
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\n",++c,sum);
73     }
74     return 0;
75 }

 

南阳1022——合纵连横(并、查、删)

标签:case   memory   error   etc   想法   去掉   div   就是   scanf   

原文地址:https://www.cnblogs.com/li-yaoyao/p/9525105.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!