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

http://begin.lydsy.com/JudgeOnline/problem.php?id=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;
}
时间: 2024-11-17 07:03:25

(最小路径覆盖) News 消息传递 (hust OJ 2604)的相关文章

Light OJ 1406 Assassin`s Creed 状态压缩DP+强连通缩点+最小路径覆盖

题目来源:Light OJ 1406 Assassin`s Creed 题意:有向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路:最少的的人能够走全然图 明显是最小路径覆盖问题 这里可能有环 所以要缩点 可是看例子又发现 一个强连通分量可能要拆分 n最大才15 所以就状态压缩 将全图分成一个个子状态 每一个子状态缩点 求最小路径覆盖 这样就攻克了一个强连通分量拆分的问题 最后状态压缩DP求解最优值 #include <cstdio> #include <cstri

Light OJ 1429 Assassin`s Creed (II) BFS+缩点+最小路径覆盖

题目来源:Light OJ 1429 Assassin`s Creed (II) 题意:最少几个人走完全图 可以重复走 有向图 思路:如果是DAG图并且每个点不能重复走 那么就是裸的最小路径覆盖 现在不是DAG 可能有环 并且每个点可能重复走 对于有环 可以缩点 缩点之后的图是DAG图 另外点可以重复走和POJ 2594一样 先预处理连通性 #include <cstdio> #include <cstring> #include <vector> #include &

[swustoj1739] 魔术球问题 (最大流,最小路径覆盖)

题目链接:https://www.oj.swust.edu.cn/problem/show/1739 从1开始枚举球的个数,每次从残余网络更新总流量,最小路径覆盖刚好大于n时ret-1便是最多球. 之后根据容量为0的边找回匹配边即可. 用x << 1和x << 1 | 1拆点 比较方便. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef struct Edge { 5 int u, v, w, n

UVAlive3126 Taxi Cab Scheme(DAG的最小路径覆盖)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32568 [思路] DAG的最小路径覆盖. 将每个人看做一个结点,如果时间允许到达就连边,则问题转化为DAG上的最小路径覆盖问题,即找到最少的路径使得每个点位于一条路径上. 算法:将DAG中的每个结点u拆分成2个为u1,u2,如果DAG中有边uv则连边u1-v2.如果该二分图的最大匹配数为ans,则答案为n-ans.可以这样想:在一条路径中除尾结点外其他结点都有且仅

hiho 第118周 网络流四&#183;最小路径覆盖

描述 国庆期间正是旅游和游玩的高峰期. 小Hi和小Ho的学习小组为了研究课题,决定趁此机会派出若干个调查团去沿途查看一下H市内各个景点的游客情况. H市一共有N个旅游景点(编号1..N),由M条单向游览路线连接.在一个景点游览完后,可以顺着游览线路前往下一个景点. 为了避免游客重复游览同一个景点,游览线路保证是没有环路的. 每一个调查团可以从任意一个景点出发,沿着计划好的游览线路依次调查,到达终点后再返回.每个景点只会有一个调查团经过,不会重复调查. 举个例子: 上图中一共派出了3个调查团: 1

hdu3861 强连通+最小路径覆盖

题意:有 n 个点,m 条边的有向图,需要将这些点分成多个块,要求:如果两点之间有路径能够互相到达,那么这两个点必须分在同一块:在同一块内的任意两点相互之间至少要有一条路径到达,即 u 到达 v 或 v 到达 u:每个点都只能存在于单独一个块内.问最少需要划分多少块. 首先,对于如果两点之间能够相互到达则必须在同一块,其实也就是在同一个强连通分量中的点必须在同一块中,所以首先就是强连通缩点.然后在同一块内的任意两点之间要有一条路,那么其实就是对于一块内的强连通分量,至少要有一条路径贯穿所有分量.

COGS728. [网络流24题] 最小路径覆盖问题

算法实现题8-3 最小路径覆盖问题(习题8-13) ´问题描述: 给定有向图G=(V,E).设P是G的一个简单路(顶点不相交)的集合.如果V中每个顶点恰好在P的一条路上,则称P是G的一个路径覆盖.P中路径可以从V的任何一个顶点开始,长度也是任意的,特别地,可以为0.G的最小路径覆盖是G的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G的最小路径覆盖. 提示: 设V={1,2,...  ,n},构造网络G1=(V1,E1)如下: 每条边的容量均为1.求网络G1的(x0,y0)最大流.

【最小路径覆盖】BZOJ2150-部落战争

[题目大意] 给出一张图,'*'表示不能走的障碍.已知每只军队可以按照r*c的方向行军,且军队与军队之间路径不能交叉.问占据全部'.'最少要多少支军队? [思路] 首先注意题意中有说“军队只能往下走”,弄清楚方向. 从某点往它能走的四个点走一趟,连边.最小路径覆盖=总数-二分图最大匹配. 哦耶!老了,连匈牙利的板子都敲错orzzzzzz 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=55; 4 int m,n

有向无环图(DAG)的最小路径覆盖

DAG的最小路径覆盖 定义:在一个有向图中,找出最少的路径,使得这些路径经过了所有的点. 最小路径覆盖分为最小不相交路径覆盖和最小可相交路径覆盖. 最小不相交路径覆盖:每一条路径经过的顶点各不相同.如图,其最小路径覆盖数为3.即1->3>4,2,5. 最小可相交路径覆盖:每一条路径经过的顶点可以相同.如果其最小路径覆盖数为2.即1->3->4,2->3>5. 特别的,每个点自己也可以称为是路径覆盖,只不过路径的长度是0. DAG的最小不相交路径覆盖 算法:把原图的每个点

hdu 3861 The King’s Problem (强连通+最小路径覆盖)

The King's Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1637    Accepted Submission(s): 600 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cit