Communication(Tarjan)

题目描述
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

思路
将整个部门视为一个强连通图,则一个部门就是一个有向图强连通分量,因此可用Tarjan算法求解

代码实现

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int N=1005;
struct node
{
    int index,to;
}pic[N];
int cnt,head[N],low[N],dfn[N],k,T,ans;
stack<int>sta;
bool vis[N];
void add(int u,int v)
{
    pic[++cnt].index=v;
    pic[cnt].to=head[u];
    head[u]=cnt;
}
void tarjan(int u)
{
    int v;
    low[u]=dfn[u]=++k;
    sta.push(u);
    vis[u]=true;
    for(int i=head[u];i;i=pic[i].to)
    {
        v=pic[i].index;
        if(dfn[v]==0)
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else
        {
            if(vis[v] && low[u]>dfn[v]) low[u]=dfn[v];
        }
    }
    if(low[u]==dfn[u])
    {
        ans++;
        do
        {
            v=sta.top();
            sta.pop();
            vis[v]=false;
        }
        while(v!=u);
    }
}
void init()
{
     cnt=0;
     ans=0;
     memset(head,0,sizeof(head));
     memset(low,0,sizeof(low));
     memset(dfn,0,sizeof(dfn));
     memset(vis,false,sizeof(vis));
     while(!sta.empty()) sta.pop();
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        init();
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
        }
        for(int i=0;i<n;i++) if(dfn[i]==0) tarjan(i);
        printf("%d\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值