# 村村通
## 题目描述
某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府 "村村通工程" 的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可)。请你计算出最少还需要建设多少条道路?
## 输入格式
输入包含若干组测试数据,每组测试数据的第一行给出两个用空格隔开的正整数,分别是城镇数目 $n$ 和道路数目 $m$ ;随后的 $m$ 行对应 $m$ 条道路,每行给出一对用空格隔开的正整数,分别是该条道路直接相连的两个城镇的编号。简单起见,城镇从 $1$ 到 $n$ 编号。
注意:两个城市间可以有多条道路相通。
**在输入数据的最后,为一行一个整数 $0$,代表测试数据的结尾。**
## 输出格式
对于每组数据,对应一行一个整数。表示最少还需要建设的道路数目。
## 样例 #1
### 样例输入 #1
```
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0
```
### 样例输出 #1
```
1
0
2
998
```
## 提示
#### 数据规模与约定
对于 $100\%$ 的数据,保证 $1 \le n < 1000$ 。
出自洛谷:P1536 村村通 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
其实就是检查有几个存子集体(大于1就是没联通完全要加一条路)
所以用查并集,每条边输入时用查并集连接,所有的连接后,遍历查并集
节点的父亲是自己就代表一个集团
ans=n-1 减一是只需要n-1条边就可以完全连接
#include
int fa[1010000];
int find(int b)
{
if(b!=fa[b])
{
fa[b]=find(fa[b]);
}
return fa[b];
}
void heping(int jl,int jp)
{
int as=find(jl);
int ad=find(jp);
fa[as]=ad;
}
就留下并查集的代码
其他的部分去掉
# 刻录光盘
## 题目描述
在JSOI2005夏令营快要结束的时候,很多营员提出来要把整个夏令营期间的资料刻录成一张光盘给大家,以便大家回去后继续学习。组委会觉得这个主意不错!可是组委会一时没有足够的空光盘,没法保证每个人都能拿到刻录上资料的光盘,又来不及去买了,怎么办呢?!
组委会把这个难题交给了LHC,LHC分析了一下所有营员的地域关系,发现有些营员是一个城市的,其实他们只需要一张就可以了,因为一个人拿到光盘后,其他人可以带着U盘之类的东西去拷贝啊!
可是,LHC调查后发现,由于种种原因,有些营员并不是那么的合作,他们愿意某一些人到他那儿拷贝资料,当然也可能不愿意让另外一些人到他那儿拷贝资料,这与我们JSOI宣扬的团队合作精神格格不入!!!
现在假设总共有N个营员(2<=N<=200),每个营员的编号为1~N。LHC给每个人发了一张调查表,让每个营员填上自己愿意让哪些人到他那儿拷贝资料。当然,如果A愿意把资料拷贝给B,而B又愿意把资料拷贝给C,则一旦A获得了资料,则B,C都会获得资料。
现在,请你编写一个程序,根据回收上来的调查表,帮助LHC计算出组委会至少要刻录多少张光盘,才能保证所有营员回去后都能得到夏令营资料?
## 输入格式
先是一个数N,接下来的N行,分别表示各个营员愿意把自己获得的资料拷贝给其他哪些营员。即输入数据的第i+1行表示第i个营员愿意把资料拷贝给那些营员的编号,以一个0结束。如果一个营员不愿意拷贝资料给任何人,则相应的行只有1个0,一行中的若干数之间用一个空格隔开。
## 输出格式
一个正整数,表示最少要刻录的光盘数。
## 样例 #1
### 样例输入 #1
```
5
2 3 4 0
4 5 0
0
0
1 0
```
### 样例输出 #1
```
1
```
这也是一道查并集的题目
但是就没有上面的那么简单了,并不是简单的集合的关系,有着a可以给b但是b不一定给a,不是双向的关系了呀.要进行一翻再进行并查集的使用处理.
很明显的转化a愿意给b,b愿意给c,可以代表a愿意给c
所以要遍历数组
#include
#include
int fa[210];
int map[210][210]={0};
int n;
int ans=0;
void chu(){
for(int h=1;h<=n;h++){
fa[h]=h;
}
}
void work(){
for(int p=1;p<=n;p++)
if(fa[p]==p)
ans++;
}
int main(){
int j=1;
scanf("%d",&n);
chu();
for(int y=1;y<=n;y++)
{
while(j>0){
scanf("%d",&j);
if(j!=0)
map[y][j]=1;//表示第y个人愿意给第j个人copy.
}
j=1;
}
for(int f=1;f<=n;f++)
for(int u=1;u<=n;u++)
for(int lp=1;lp<=n;lp++){
if(map[u][f]==1&&map[f][lp]==1)//u愿意给k,k 愿意给lp那就是u愿意给lp
map[u][lp]=1;
}
for(int ji=1;ji<=n;ji++){
for(int jl=1;jl<=n;jl++)
if(map[ji][jl]==1)
fa[jl]=fa[ji];
}
work();
printf("%d",ans);
return 0;
}
处理完就可以并查集ko了(数据不大甚至不需要用路径的压缩).
并查集就是对若干的数据建立逻辑关系,以及集合关系
用数组表示值就是自己上级(父亲)的下标,当自己的值等于自己时,就代表一个集合,但是集合内部成员数量不一定.
可以解决很多的关系问题,如亲戚,铁路,电网.
ok今天就是简简单单的看看了之前学习的,明天训练一下
!