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;
}

 

 

posted on 2016-06-01 17:47  栀蓝  阅读(359)  评论(0编辑  收藏  举报

levels of contents