zoukankan      html  css  js  c++  java
  • hihoCoder:1394 : 网络流四·最小路径覆盖

    https://hihocoder.com/problemset/problem/1394

    描述

    国庆期间正是旅游和游玩的高峰期。

    小Hi和小Ho的学习小组为了研究课题,决定趁此机会派出若干个调查团去沿途查看一下H市内各个景点的游客情况。

    H市一共有N个旅游景点(编号1..N),由M条单向游览路线连接。在一个景点游览完后,可以顺着游览线路前往下一个景点。

    为了避免游客重复游览同一个景点,游览线路保证是没有环路的。

    每一个调查团可以从任意一个景点出发,沿着计划好的游览线路依次调查,到达终点后再返回。每个景点只会有一个调查团经过,不会重复调查。

    举个例子:

    上图中一共派出了3个调查团:

    1. 蓝色:调查景点;2

    2. 橙色:调查景点;1->3->4->6

    3. 绿色:调查景点;5->7

    当然对于这个图还有其他的规划方式,但是最少也需要3个调查团。

    由于小组内的人数有限,所以大家希望调查团的数量尽可能少,同时也要将所有的景点都进行调查。

    当然,如何规划调查团线路的任务落到了小Hi和小Ho的头上。

    提示:最小路径覆盖

    输入

    第1行:2个整数N,M。1≤N≤500,0≤M≤20,000。

    第2..M+1行:2个数字u,v,表示一条有向边(u,v)。保证不会出现重复的边,且不存在环。

    输出

    第1行:1个整数,表示最少需要的调查团数量。

    样例输入

    7 7
    1 2
    1 3
    2 4
    3 4
    4 5
    4 6
    5 7

    样例输出

    3

    匈牙利算法:

    #include <stdio.h>
    #include <string.h>
    #define N 550
    int e[N][N], book[N], pre[N];
    int n, m;
    int dfs(int u)
    {
    	int v;
    	for (v = 1; v <= n; v++){
    		if (e[u][v] && book[v] == 0){
    			book[v] = 1;
    			if (pre[v] == 0 || dfs(pre[v])){
    				pre[v] = u;	
    				return 1;
    			}
    				
    		}
    	}
    	return 0;
    }
    
    int main()
    {
    	int u, v, sum, i;
    	while (scanf("%d%d", &n, &m) != EOF) {
    		for (i = 0; i < m; i++) {
    			scanf("%d%d", &u, &v);
    			e[u][v] = 1;
    		}
    		sum = 0;
    		for (i = 1; i <= n; i++)
    		{
    			memset(book, 0, sizeof(book));
    			if (dfs(i))
    				sum++;
    		}
    		printf("%d
    ", n - sum);
    	}
    	return 0;
    }

     EK算法:

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    #include <algorithm>
    #define N 1020
    using namespace std;
    int n, m, inf=0x7f7f7f;
    int e[N][N], pre[N], flow[N];
    int bfs(int s, int t)
    {
    	int u, v;
    	queue<int>q;
    	flow[s] = inf;		
    	q.push(s);
    	while (!q.empty()){
    		u = q.front();
    		q.pop();
    		if (u == t)
    			break;
    		for (v = 0; v <= 2 * n + 1; v++)
    		{	
    			if (e[u][v] && pre[v] == -1 && v!=s)
    			{
    				q.push(v);
    				pre[v] = u;
    				flow[v] = min(flow[u], e[u][v]);
    			}
    		}
    	}
    	if (pre[t] == -1)
    		return -1;
    	return flow[t];
    }
    
    int EK(int s, int t)
    {
    	int d, p, sum = 0;
    	while (1){
    		memset(pre, -1, sizeof(pre));
    		d = bfs(s, t);
    		if (d == -1)
    			return sum;
    		sum += d;
    		p = t;
    		while (p != s) {
    			e[pre[p]][p] -= d;
    			e[p][pre[p]] += d;
    			p = pre[p];
    		}
    	}
    	return sum;
    }
    int main()
    {
    	int u, v, i;
    	while (scanf("%d%d", &n, &m) != EOF){
    		memset(e, 0, sizeof(e));
    		for (i = 0; i < m; i++){
    			scanf("%d%d", &u, &v);
    			e[u][v+n] = 1;
    		}
    		for (i = 1; i <= n; i++) {
    			e[0][i] = 1;
    			e[n + i][2 * n + 1] = 1;
    		}
    		printf("%d
    ", n - EK(0, 2 * n + 1));
    	}
    	return 0;
    }
  • 相关阅读:
    如何在vim中同时编辑多个文件
    Windows操作系统架构
    驱动中PAGED_CODE的作用
    Process Hacker源码中的用户态hook的做法
    IO Processing
    Device Drivers
    Windows IO System
    how to catch error in make error message
    分析/proc/[pid]/maps中的各个内存区域的大小
    boost::shared_ptr
  • 原文地址:https://www.cnblogs.com/zyq1758043090/p/11852582.html
Copyright © 2011-2022 走看看