﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-I believe-随笔分类-并查集*哈希表*类似</title><link>http://www.cppblog.com/luyulaile/category/11068.html</link><description>I  can</description><language>zh-cn</language><lastBuildDate>Sun, 05 Jul 2009 17:04:43 GMT</lastBuildDate><pubDate>Sun, 05 Jul 2009 17:04:43 GMT</pubDate><ttl>60</ttl><item><title>poj 1611  the suspect 并查集</title><link>http://www.cppblog.com/luyulaile/archive/2009/07/03/89172.html</link><dc:creator>luis</dc:creator><author>luis</author><pubDate>Fri, 03 Jul 2009 08:51:00 GMT</pubDate><guid>http://www.cppblog.com/luyulaile/archive/2009/07/03/89172.html</guid><wfw:comment>http://www.cppblog.com/luyulaile/comments/89172.html</wfw:comment><comments>http://www.cppblog.com/luyulaile/archive/2009/07/03/89172.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/luyulaile/comments/commentRss/89172.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/luyulaile/services/trackbacks/89172.html</trackback:ping><description><![CDATA[<p class=pst>Description</p>
<p class=pst>Description</p>
<div class=ptx lang=en-US>Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. To minimize transmission to others, the best strategy is to separate the suspects from others. <br>In the Not-Spreading-Your-Sickness University (NSYSU), there are many student groups. Students in the same group intercommunicate with each other frequently, and a student may join several groups. To prevent the possible transmissions of SARS, the NSYSU collects the member lists of all student groups, and makes the following rule in their standard operation procedure (SOP). <br>Once a member in a group is a suspect, all members in the group are suspects. <br>However, they find that it is not easy to identify all the suspects when a student is recognized as a suspect. Your job is to write a program which finds all the suspects.</div>
<p class=pst>Input</p>
<div class=ptx lang=en-US>The input file contains several cases. Each test case begins with two integers n and m in a line, where n is the number of students, and m is the number of groups. You may assume that 0 &lt; n &lt;= 30000 and 0 &lt;= m &lt;= 500. Every student is numbered by a unique integer between 0 and n&#8722;1, and initially student 0 is recognized as a suspect in all the cases. This line is followed by m member lists of the groups, one line per group. Each line begins with an integer k by itself representing the number of members in the group. Following the number of members, there are k integers representing the students in this group. All the integers in a line are separated by at least one space. <br>A case with n = 0 and m = 0 indicates the end of the input, and need not be processed.</div>
<p class=pst>Output</p>
<div class=ptx lang=en-US>For each case, output the number of suspects in one line.</div>
<p class=pst>Sample Input</p>
<pre class=sio>100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0</pre>
<p class=pst>Sample Output</p>
<pre class=sio>4
1
1</pre>
<p>启示1，一定注意初始化带来的影响，1，是什么地方初始化，2，前一个case不应当对下一个造成影响<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2，有层次性的问题一定要处理好，不要<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3，例如重复数据不能重复初始化。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cin&gt;&gt;t;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(father[t]&lt;0)//必不可少<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;father[t]=t;<br><br><br>#include&lt;iostream&gt;<br>#include&lt;cstdlib&gt;<br>using namespace std;<br>&nbsp; int rank[30001];<br>&nbsp; int father[30001];<br>&nbsp; void UNION(int a,int b)<br>&nbsp; {<br>&nbsp;&nbsp;if(a==b)return;<br>&nbsp;&nbsp;else<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;if(rank[a]&lt;rank[b])<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;father[b]=father[a];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;else<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;father[a]=father[b];<br>&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;<br>&nbsp; }<br>&nbsp; int Find(int t)<br>&nbsp; {<br>&nbsp;&nbsp;int tmp=t,x;<br>&nbsp;&nbsp;while(father[tmp]!=tmp)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;tmp=father[tmp];<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;while(t!=father[t])<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x=t;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t=father[x];<br>&nbsp;&nbsp;&nbsp;father[x]=tmp;<br>&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; return t;<br>&nbsp; }<br>&nbsp; int main()<br>&nbsp; {<br>&nbsp; freopen("s.txt","r",stdin);<br>&nbsp; freopen("key.txt","w",stdout);<br>&nbsp; int i,j,nt,t1,t,result;<br>&nbsp; while(cin&gt;&gt;i&gt;&gt;j,i||j)<br>&nbsp; {<br>&nbsp;&nbsp;result=0;<br>&nbsp;&nbsp;memset(rank,1,sizeof(rank));<br>&nbsp;&nbsp;memset(father,-1,sizeof(father));<br>&nbsp;&nbsp;rank[0]=0;<br>&nbsp;&nbsp;father[0]=0;<br>&nbsp;for(int k=0;k&lt;j;k++)<br>&nbsp;{<br>&nbsp;&nbsp;cin&gt;&gt;nt;<br>&nbsp;&nbsp;cin&gt;&gt;t1;<br>&nbsp;&nbsp;rank[t1]=t1;<br>&nbsp;&nbsp;if(father[t1]&lt;0)<br>&nbsp;&nbsp;&nbsp;&nbsp;father[t1]=t1;<br>&nbsp;&nbsp;for(int m=1;m&lt;nt;m++)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;cin&gt;&gt;t;<br>&nbsp;&nbsp;&nbsp;rank[t]=t;<br>&nbsp;&nbsp;&nbsp;if(father[t]&lt;0)<br>&nbsp;&nbsp;&nbsp;&nbsp;father[t]=t;<br>&nbsp;&nbsp;&nbsp;UNION(Find(t1),Find(t));<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;for(int l=0;l&lt;i;l++)<br>&nbsp;{<br>&nbsp;&nbsp;if(father[l]&gt;=0)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;if(!Find(l))<br>&nbsp;&nbsp;result++;<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;}<br>&nbsp;cout&lt;&lt;result&lt;&lt;endl;<br>&nbsp;&nbsp;<br>&nbsp; }</p>
<p>&nbsp; //system("PAUSE");<br>&nbsp; return&nbsp;&nbsp; 0;<br>&nbsp; }</p>
<img src ="http://www.cppblog.com/luyulaile/aggbug/89172.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/luyulaile/" target="_blank">luis</a> 2009-07-03 16:51 <a href="http://www.cppblog.com/luyulaile/archive/2009/07/03/89172.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>哈希表 poj 3320 Jessica's Reading Problem</title><link>http://www.cppblog.com/luyulaile/archive/2009/07/01/88982.html</link><dc:creator>luis</dc:creator><author>luis</author><pubDate>Wed, 01 Jul 2009 05:00:00 GMT</pubDate><guid>http://www.cppblog.com/luyulaile/archive/2009/07/01/88982.html</guid><wfw:comment>http://www.cppblog.com/luyulaile/comments/88982.html</wfw:comment><comments>http://www.cppblog.com/luyulaile/archive/2009/07/01/88982.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/luyulaile/comments/commentRss/88982.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/luyulaile/services/trackbacks/88982.html</trackback:ping><description><![CDATA[<p>poj 3320 Jessica's Reading Problem <a href="http://acm.pku.edu.cn/JudgeOnline/problem?id=3320">http://acm.pku.edu.cn/JudgeOnline/problem?id=3320</a><br>这道题目可以用哈希表法也可以用二分查找法，现在用哈希，二分查找将在后面的博客中推出。<br>这道题目用到的是数的哈希，对于不需要删除的字典，哈希表是一种理想的实现方式。<br>1.哈希表的插入和查找算法<br>(1)计算函数值h(k)<br>(2)从槽h(k)开始，使用冲突解决策略定位包含关键码k的纪录<br>(3)如果需要插入，再槽内插入即可<br>两种操作的复杂度在忽略冲突时是O(1)<br>2.哈希函数的选取<br>本题使用最简单的直接取余法，除数为PRIME，最好是质数，可减小冲突。<br>3.冲突解决方法<br>开散列法（这也是大多数情况下使用的）<br>开散列法也叫拉链法，通俗地说就是&#8220;既然元素a和b都该放在里面，只好挤一挤了&#8221;。即在每个槽里存放所有该放在里面的元素。那么怎么把很多的元素放在槽里呢？只在槽里放一个链表表头就行了，该链表中包含所有该放在槽里的元素。但在实际中并不是这样做的，而是自己维护一个大数组，给链表元素分配数组下标，这样既方便又节省时间和空间。那么链表中的元素的排列顺序怎样呢？如果按照查找成功时的效率，显然可以按照访问的频率；而如果按照查找失败的效率，则可以按照关键值排序，即使查找失败也不需要遍历整个链表。这就是数据结构中的相互矛盾的两个问题，应根据实际情况协调。<br>#include&lt;stdio.h&gt;<br>#define PRIME 99991<br>struct hashnode<br>{<br>&nbsp;&nbsp;&nbsp; int key;<br>&nbsp;&nbsp;&nbsp; int num;<br>&nbsp;&nbsp;&nbsp; int next;<br>}a[1000005];<br>int b[1000005];<br>int hashl;<br>int hash(int num)<br>{<br>&nbsp;&nbsp;&nbsp; int i;<br>&nbsp;&nbsp;&nbsp; i=num%PRIME;<br>&nbsp;&nbsp;&nbsp; while(a[i].next!=-1)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(num&gt;a[a[i].next].key)&nbsp;&nbsp;&nbsp;&nbsp; //例如hash表中已有8，后面又插入99999时，那么99999&gt;8,需要给99999重新分配&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个下标，即hashl，即前面提到的开散列法解决冲突<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if(num==a[a[i].next].key)&nbsp;&nbsp;&nbsp; //例如hash表中已有8，后面又插入8时，这是只要num++<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a[i].next;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i=a[i].next;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //这句用于查找，如果哈希表中已有8和99999，那么你要找8时a[8].next指向的是较大的99999，那么你就必须沿着next走下去，因为这个所谓的链表是按减小的顺序排序的。最终走到return a[i].next推出while 循环<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; a[hashl].key=num;<br>&nbsp;&nbsp;&nbsp; a[hashl].next=-1;<br>&nbsp;&nbsp;&nbsp; a[hashl].num=0;<br>&nbsp;&nbsp;&nbsp; a[hashl].next=a[i].next;<br>&nbsp;&nbsp;&nbsp; a[i].next=hashl;<br>&nbsp;&nbsp;&nbsp; hashl++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //以上6行用于第一次插入元素（即while循环未执行）或while循环break退出的插入<br>&nbsp;&nbsp;&nbsp; return hashl-1;<br>}</p>
<p>int main()<br>{<br>&nbsp;&nbsp;&nbsp; int n,i,tmp,left,ans;<br>&nbsp;&nbsp;&nbsp; while(scanf("%d",&amp;n)!=EOF)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(i=0;i&lt;PRIME;i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a[i].next=-1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hashl=PRIME;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; left=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ans=1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scanf("%d",&amp;b[0]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp=hash(b[0]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a[tmp].num++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(i=1;i&lt;n;i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scanf("%d",&amp;b[i]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp=hash(b[i]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a[tmp].num++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(a[tmp].num&lt;=1)&nbsp;&nbsp;&nbsp;&nbsp; //插入的数字以前没有出现过，肯定包含在ans里<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ans=i-left+1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //对应于if的else,即a[tmp].num&gt;=2，即插入的数字以前出现过。如果是在left位置出现过，则left右移；如果是在&#8220;left右边，i左边&#8221;出现过，则说明目前的i-left+1和ans都可以包括全部的知识点，当然取小的了！&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp=hash(b[left]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(a[tmp].num&lt;=1)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a[tmp].num--;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; left++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(ans&gt;i-left+1)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ans=i-left+1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%d\n",ans);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return 0;<br>}</p>
<p><br>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/cugbliang/archive/2008/06/01/2497376.aspx">http://blog.csdn.net/cugbliang/archive/2008/06/01/2497376.aspx</a></p>
<img src ="http://www.cppblog.com/luyulaile/aggbug/88982.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/luyulaile/" target="_blank">luis</a> 2009-07-01 13:00 <a href="http://www.cppblog.com/luyulaile/archive/2009/07/01/88982.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>