zoukankan      html  css  js  c++  java
  • 【洛谷 P2764】 最小路径覆盖问题(最大流)

    题目链接
    首先有(n)条路径,每条路径就是一个点,然后尽量合并,答案就是点数-合并数。
    套路拆点,源连入,出连汇,原有的边入出连。
    最大流就是最大合并数,第一问解决。
    然后怎么输出方案?
    我是找到所有路径中的最后一个点,然后根据残量网络一直往前跳,(dfs)倒序输出。

    #include <cstdio>
    #include <queue>
    #include <cstdlib>
    #include <cstring>
    #define INF 2147483647
    using namespace std;
    const int MAXN = 360;
    const int MAXM = 16010;
    struct point{
        int x, y, time;
    }Now;
    queue <int> q;
    struct Edge{
        int from, to, next, rest;
    }e[MAXM];
    int head[MAXN], num = 1, s, t, now, n, m, dis[MAXN], a, b;
    inline void Add(int from, int to, int flow){
        e[++num] = (Edge){ from, to, head[from], flow }; head[from] = num;
        e[++num] = (Edge){ to, from, head[to], 0 }; head[to] = num;
    }
    int re(){
        memset(dis, 0, sizeof dis);
        q.push(s); dis[s] = 1;
        while(q.size()){
        	now = q.front(); q.pop();
        	for(int i = head[now]; i; i = e[i].next)
        	   if(e[i].rest && !dis[e[i].to])
        	     dis[e[i].to] = dis[now] + 1, q.push(e[i].to);
        }
        return dis[t];
    }
    int find(int u, int flow){
        if(u == t || !flow) return flow;
        int sum = 0, T;
        for(int i = head[u]; i; i = e[i].next)
           if(e[i].rest && dis[e[i].to] == dis[u] + 1){
           	 T = find(e[i].to, min(flow - sum, e[i].rest));
             e[i].rest -= T; e[i ^ 1].rest += T; sum += T;
           }
        if(!sum) dis[u] = 0;
        return sum;
    }
    int dinic(){
        int ans = 0;
        while(re()) ans += find(s, INF);
        return ans;
    }
    void dfs(int u){
    	for(int i = head[u + n]; i; i = e[i].next)
    	   if(e[i].to <= n && e[i].rest)
    	     dfs(e[i].to);
    	printf("%d ", u);
    }
    int ans;
    int main(){
        scanf("%d%d", &n, &m); s = 345; t = 350;
        for(int i = 1; i <= m; ++i){
           scanf("%d%d", &a, &b);
           Add(a, b + n, 1);
        }
        for(int i = 1; i <= n; ++i)
           Add(s, i, 1), Add(i + n, t, 1);
        ans = n - dinic();
        for(int i = 1; i <= n; ++i){
        	int flag = 1;
        	for(int j = head[i]; j; j = e[j].next)
        	   if(e[j].to > n && e[j].to <= 2 * n && !e[j].rest){
        	   	 flag = 0; break;
        	   }
        	if(flag) dfs(i),
        	putchar('
    ');
        }
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    windows下的定时任务设置详解
    php实现 字符串分割
    js进阶 11-7 jquery如何获取和改变元素的位置
    js进阶 11-6 jquery如何获取和设置元素的宽高(jquery多方法)
    详解PHP设置定时任务的实现方法
    详解PHP实现定时任务的五种方法
    百度echarts可以做什么
    前端开发框架对比(工具可以从框架中找)(好的框架,事半功倍)
    poj 3080 Blue Jeans
    ZOJ 3822 可能性DP
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/10541461.html
Copyright © 2011-2022 走看看