zoukankan      html  css  js  c++  java
  • (最小路径覆盖) 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-ans);
    
        return 0;
    }
  • 相关阅读:
    nodejs游戏服务器开发(二)---mysql连接
    nodejs游戏服务器开发(一)---socket连接
    《Metasploit渗透测试指南》命令参考列表
    Nmap脚本使用总结(转乌云) 下
    Nmap的介绍和使用(乌云转) 上
    局域网win7系统:虚拟机kali 做端口映射
    漏洞检测的几种方法
    BurpSuite 1.6.27 最新破解版操作
    Metasploit基础
    龙灵:特邀国内第一讲师“玄魂” 在线培训黑客神器Kali Linux
  • 原文地址:https://www.cnblogs.com/YY56/p/5550475.html
Copyright © 2011-2022 走看看