首页 > 其他 > 详细

洛谷P4843 清理雪道(有源汇的上下界的网络流)

时间:2020-02-16 23:24:13      阅读:72      评论:0      收藏:0      [点我收藏+]

 题目链接

题目大意

给定一个有向无环图,求最小边覆盖

做法

  • 考虑网络流算法。
  • 建立源点s和汇点t,由于可以从任意一个点开始,也可以从任意一个点结束,所以对于每一个点u连边s -> u,u -> t
  • 由于是最小覆盖,所以对于原图给定的有向边信息(u,v),改成连一条上界为inf,下界为1的有向边(u,v)
  • 求该图的最小流即可。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 1000000000
#define maxN 505
using namespace std;

int N, S, T, s, t;

int d[maxN];

struct Edge {
    int dis, nxt, to;
}e[20005];
int cnte = 1, head[maxN];

inline void add_Edge(int i, int j, int k) { 
    e[++cnte].dis = k, e[cnte].nxt = head[i], e[cnte].to = j, head[i] = cnte; 
    e[++cnte].dis = 0, e[cnte].nxt = head[j], e[cnte].to = i, head[j] = cnte;
}

inline void Add(int u, int v, int down, int up) {
    add_Edge(u, v, up - down), d[v] += down, d[u] -= down;
}

void Build() {
    cin >> N;
    s = N + 1, t = N + 2, S = N + 3, T = N + 4;
    for(int i = 1, m; i <= N; ++i) {
        cin >> m,
        Add(i, t, 0, INF), Add(s, i, 0, INF);
        for(int j = 1, to; j <= m; ++j) {
            cin >> to, 
            Add(i, to, 1, INF);
        }
    }
    for(int i = 1; i <= t; ++i) {
        if(d[i] > 0) add_Edge(S, i, d[i]);
        else if(d[i] < 0) add_Edge(i, T, -d[i]);
    }
}
int dep[maxN];
bool bfs() {
    queue <int> Q;
    memset(dep, 0, sizeof(dep));
    dep[S] = 1, Q.push(S);
    while(!Q.empty()) {
        int u = Q.front(); Q.pop();
        for(int v, i = head[u]; i; i = e[i].nxt) {
            if(!dep[v = e[i].to] && e[i].dis) {
                dep[v] = dep[u] + 1, Q.push(v);
            }
        }
    }
    return dep[T];
}
int dfs(int u, int in) {
    if(u == T) return in;
    int out = 0;
    for(int v, i = head[u]; i && in; i = e[i].nxt) {
        if(e[i].dis && dep[v = e[i].to] == dep[u] + 1) {
            int tmp = dfs(v, min(in, e[i].dis));
            e[i].dis -= tmp, e[i ^ 1].dis += tmp,
            in -= tmp, out += tmp;
        }
    }
    if(!out) dep[u] = 0;
    return out;
}
int main() {
    Build();
    while(bfs()) dfs(S, INF);
    add_Edge(t, s, INF);
    while(bfs()) dfs(S, INF);    
    cout << e[cnte].dis << \n;
    return 0;
} 

 

 

洛谷P4843 清理雪道(有源汇的上下界的网络流)

原文:https://www.cnblogs.com/blog-fgy/p/12319047.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!