休假 复习

# 村村通

## 题目描述

某市调查城镇交通状况,得到现有城镇道路统计表。表中列出了每条道路直接连通的城镇。市政府 "村村通工程" 的目标是使全市任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要相互之间可达即可)。请你计算出最少还需要建设多少条道路?

## 输入格式

输入包含若干组测试数据,每组测试数据的第一行给出两个用空格隔开的正整数,分别是城镇数目 $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今天就是简简单单的看看了之前学习的,明天训练一下

!

你可能感兴趣的:(学习)