Communication【floyd判环+并查集】

Communication

题目链接(点击)

题目描述

The Ministry of Communication has an extremely wonderful message system, designed by the President himself. For maximum efficiency, each office in the Ministry can send a message directly to some, but not necessarily all, other offices. These connections are not always two-way, because sometimes one office should have the power to send a message to another office, but the other office should not have the power to send one back. This may seem unfair, or even illogical, to uneducated people, but this is the will of the President. 
There are so many offices now that the situation has become rather confusing, so the President has decided to reorganize the Ministry to be better adapted to the message system. 
The President will divide the Ministry into new departments based on two simple principles: 
1.  If A and B are in the same department then A can transmit a message to B, and B can transmit a message to A. 
2.  If A can transmit a message to B, and B can transmit a message to A, then A and B are in the same department. 
How many departments will the reorganized Ministry have? 

 

输入

Input starts with a line containing a single integer N, with 0 < N ≤ 100. This tells you how many test cases there will be. 
Each following pair lines contains a single test case. The first line of each test case contains an integer n, with 1 < n ≤ 200. This is the number of offices the Ministry has. The second line starts with an integer e with 0 < e <n2/4. This tells you how many individual direct (and directed) connections the Ministry has. Following this are e pairs of integers a, b, with 0 ≤a < b ≤ n − 1. These pairs indicate that there is a connection from a to b. There is at most one direct connection going out from one office and into another. 

输出

Each line of output is an integer saying how many departments the Ministry corresponding to that test case will have.  

样例输入

3
6
2 0 5 5 0
5
7 0 1 0 2 1 0 1 3 2 4 3 1 4 2
3
4 0 1 0 2 1 0 1 2

样例输出

5
2
2

题意:

T组数据 每组先输入一个数n表示共n个点  然后是m和m组关系 (a,b)表示a可以给b发消息 如果满足以下条件的一种 则可以将他们划分到一组:

1、1-->2  && 2-->1   (相互之间可以直接通信)

2、1-->2 && 2-->3 && 3-->1  (成环)(题意中没说明 只考虑1WA了所以想到可能有这种情况)

最后输出可以分成几组

思路:

先标记那两个点之间有关系 因为想使用并查集 但并查集的边是无方向的 所以必须满足两点之间可以相互通话才使用并查集连接

分两种情况对待1、2的判断条件:

1、如果f[i][j]=1&&f[j][i]=1说明他们符合条件1并且是双向的边 那就可以把它们放进并查集

2、条件是成环 所以用floyd先判断是否成环:如果成环 则dis[i][j]和dis[j][i]一定是小于初始化的值的 也把他们放进并查集

最后跑for 判断有几个点的pre[i]==i 输出个数即可

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int MAX=2e2;
const int INF=0x3f3f3f3f;
int n,m;
int f[MAX+5][MAX+5];
int pre[MAX+5];
int dis[MAX+5][MAX+5];
void floyd()
{
    for(int k=0;k<n;k++){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(dis[i][j]>dis[i][k]+dis[k][j]){
                    dis[i][j]=dis[i][k]+dis[k][j];
                }
            }
        }
    }
}
int judge(int i, int j)
{
    if(dis[i][j]<INF&&dis[j][i]<INF){
        return 1;
    }
    return 0;
}
int fd(int x)
{
    int r=x;
    while(pre[r]!=r){
        r=pre[r];
    }
    return r;
}
void mix(int x,int y)
{
    int fx=fd(x),fy=fd(y);
    if(fx!=fy){
        pre[fx]=fy;
    }
}
void init()
{
    for(int i=0;i<MAX;i++){
        pre[i]=i;
        for(int j=0;j<MAX;j++){
            f[i][j]=0;
            dis[i][j]=INF;
        }
    }
}
struct node{
    int u;
    int v;
}a[MAX+5];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        init();
        for(int i=0;i<m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            a[i].u=u,a[i].v=v;
            f[u][v]=1;
            dis[u][v]=1;
        }
        floyd();
        for(int i=0;i<m;i++){
            int u=a[i].u,v=a[i].v;
            if(f[v][u]==1||judge(u,v)){
                mix(u,v);
            }
        }
        int ans=0;
        for(int i=0;i<n;i++){
            if(pre[i]==i){
                ans++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Floyd判圈算法,又称龟兔赛跑算法,是用来判断链表是否有环、计算环的长度以及寻找环的起点的一种算法。该算法通过使用两个指针,一个慢指针和一个快指针,在链表中进行遍历。慢指针每次移动一步,而快指针每次移动两步。如果链表中存在环,那么快指针最终会追上慢指针,两个指针会相遇。这可以通过两个条件来判断:当快指针和慢指针相遇时,且快指针不为null且快指针的下一个节点也不为null。如果两个指针相遇,那么说明链表中存在环。接下来,我们可以从相遇点开始,用一个指针再次遍历链表,直到回到相遇点,记录遍历过程中的节点数。这个节点数就是环的长度。 如果慢指针和快指针相遇,那么我们可以进一步判断是否有环存在。如果相遇点是链表中的某个节点,那么从相遇点开始遍历链表,再次回到相遇点的位置一定是环的起点。这是因为从相遇点继续遍历,最终会再次回到相遇点,而在这个过程中,慢指针每次移动一步,快指针每次移动两步,所以在某一时刻,慢指针和快指针会在环的起点处相遇。 然而,如果慢指针和快指针从环的不同起点出发,那么它们再次相遇的位置会发生偏移,不会是环的起点。同样地,如果慢指针和快指针从环外的同一起点出发,它们在进入环之前还有一段距离,因此再次相遇的位置也不一定是环的起点。 综上所述,Floyd判圈算法通过两个指针的移动,可以判断链表是否有环,并且计算出环的长度和寻找环的起点。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Floyd判圈算法](https://blog.csdn.net/qq_26012495/article/details/117407011)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [cjing-interview:C ++面试; 基本算法数据结构提示](https://download.csdn.net/download/weixin_42144707/16474761)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值