(最小路径覆盖) News 消息传递 (hust OJ 2604)

Posted 栀蓝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(最小路径覆盖) News 消息传递 (hust OJ 2604)相关的知识,希望对你有一定的参考价值。

 

Description

总部最近打算向下面的N个工作人员发出了一条秘密消息。因为它是机密,所以只能一对一的传递消息,也就是说每一个人知道消息之后只能把消息传给他能够传达到的且还未知道该消息的若干个人中的一个。对于A、B两个人,可能存在A能够传消息给B,而B无法传消息给A的情况。现在总部为了防止消息被泄露,命令你计算最开始总部至少要告诉多少人消息,才能保证最终所有人都知道了这个消息。

Input

第一行,N、M。
接下来M行,每行两个数字A、B,表示A号能够传消息给B号。
(N个人的编号是1~N)
1≤N≤100 000
1≤M≤300 000 

Output

一个数字,最少需要由总部告知的人数

Sample Input

4 3
1 4
4 3
1 2

Sample Output

2

 

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;

#define N 100100
#define INF 0xfffffff


struct Node
{
    int v, next;
} a[N*3];

int  head[N], cnt, n, m;
bool used[N];
int  Mx[N], My[N], depth; ///记录的所匹配的端点,0表示未匹配
int  dx[N], dy[N]; ///BFS分层时,记录点所在的层,-1表示不在分层

void Init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
}

void Add(int u, int v)
{
    a[cnt].v = v;
    a[cnt].next = head[u];
    head[u] = cnt++;
}

bool BFS()///如果发现y这边有增广路,返回1,否则返回0
{
    queue<int> Q;
    depth = INF;

    memset(dx, -1, sizeof(dx));
    memset(dy, -1, sizeof(dy));

    for(int i=1; i<=n; i++)
    {
        if( Mx[i] == false )
        {
            dx[i] = 0;
            Q.push(i);
        }
    }

    while(Q.size())
    {
        int u = Q.front();
        Q.pop();
        if(dx[u] > depth) break;///已经找到了增广路,不必寻找下层

        for(int j=head[u]; j!=-1; j=a[j].next)
        {
            int v = a[j].v;

            if( dy[v] == -1 )
            {
                dy[v] = dx[u] + 1;

                if(My[v] == false)
                    depth = dy[v];
                else
                {
                    dx[ My[v] ] = dy[v] + 1;
                    Q.push( My[v] );
                }
            }
        }
    }

    if( depth == INF )
        return false;
    return true;
}
bool Find(int i)
{
    for(int j=head[i]; j!=-1; j=a[j].next)
    {
        int v = a[j].v;

        if( !used[v] && dx[i] == dy[v]-1)
        {
            used[v] = true;

            if( My[v] && dy[v] == depth )
                continue;///不会在下一层,因为还没有对下层进行增广

            if( !My[v] || Find( My[v] ) )
            {
                My[v] = i;
                Mx[i] = v;
                return true;
            }
        }
    }

    return false;
}

int Karp()
{
    int ans = 0;
    memset(Mx, false, sizeof(Mx));
    memset(My, false, sizeof(My));

    while( BFS() == true )
    {
        ///如果还存在增广路
        memset(used, false, sizeof(used));
        for(int i=1; i<=n; i++)
        {
            if( !Mx[i] && Find(i) == true )
                ans++;
        }
    }

    return ans;
}

int main()
{
    int m, i, x, y;

    scanf("%d%d", &n, &m);
    Init();

    for(i=1; i<=m; i++)
    {
        scanf("%d%d", &x, &y);
        Add(x, y);
    }

    int ans = Karp();

    printf("%d\n", n-ans);

    return 0;
}

 

 

以上是关于(最小路径覆盖) News 消息传递 (hust OJ 2604)的主要内容,如果未能解决你的问题,请参考以下文章

POJ2594 Treasure Exploration(最小路径覆盖+传递闭包)

POJ2594 Treasure Exploratio —— 最小路径覆盖 + 传递闭包

HUST 1027 Enemy Target!

POJ 2594 Treasure Exploration(Floyd+最小路径覆盖)

POJ 2594 Treasure Exploration 最小可相交路径覆盖

POJ 2594 Treasure Exploration(最小路径覆盖变形)