zoukankan      html  css  js  c++  java
  • 洛谷P2764 最小路径覆盖问题

    有向无环图的最小路径点覆盖

    最小路径覆盖就是给定一张DAG,要求用尽量少的不相交的简单路径,覆盖有向无环图的所有顶点。
    有定理:顶点数-路径数=被覆盖的边数。

    要理解的话可以从两个方向:

    • 假设DAG已经被n条路径覆盖,那么任意一条路径又有 顶点数-1=边数。那么对所有路径等式两边求和,每条路径的顶点数之和=所有点数,-1的和=路径数,每条路径的边数之和=被覆盖的边数。。这样上面的定理就成立了。

    • 还有一种方法,我们要先引入二分图

    我们把原图中的点拆成出点(边从该点出)和入点(边从该点入),即原图点x在二分图中对应出点x,入点x+n。
    原图中的边(x,y)对应二分图中的(x,y+n)。我们每次选择路径,因为边不能相交,所以对于一个点,只有一个入和一个出,这显然是一个匹配问题。
    选择的边(x,y)相当于从源点s到x,从x到y+n,从y+n到汇点t有了单位流量。
    特别的,如果一个点是路径的终点,那么他没有出度,即该点二分匹配失败。
    可以显然得出,最后匹配失败的点数就是路径数。
    因为源点相连的点一定有n个,所以有 顶点数-路径数=二分图最大匹配。
    且由上述概念得二分图最大匹配即为路径选择的边数(被覆盖的边数)

    所以我们把题目给的点拆开跑最大流就可以啦!

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    using namespace std;
    typedef long long ll;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int X = 0, w = 0; char ch = 0;
        while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        return w ? -X : X;
    }
    inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
    inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
    template<typename T>
    inline T max(T x, T y, T z){ return max(max(x, y), z); }
    template<typename T>
    inline T min(T x, T y, T z){ return min(min(x, y), z); }
    template<typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 505;
    const int M = 6005;
    int n, m, cnt, head[N], depth[N], to[N], vis[N];
    struct Edge { int v, next, f; } edge[M<<5];
    
    void addEdge(int a, int b, int f){
        edge[cnt].v = b, edge[cnt].f = f, edge[cnt].next = head[a], head[a] = cnt ++;
        edge[cnt].v = a, edge[cnt].f = 0, edge[cnt].next = head[b], head[b] = cnt ++;
    }
    
    bool bfs(){
        full(depth, 0);
        queue<int> q;
        depth[0] = 1, q.push(0);
        while(!q.empty()){
            int s = q.front(); q.pop();
            for(int i = head[s]; i != -1; i = edge[i].next){
                int u = edge[i].v;
                if(!depth[u] && edge[i].f > 0){
                    depth[u] = depth[s] + 1;
                    q.push(u);
                }
            }
        }
        return depth[2 * n + 1] != 0;
    }
    
    int dfs(int s, int a){
        if(s == 2 * n + 1) return a;
        int flow = 0;
        for(int i = head[s]; i != -1; i = edge[i].next){
            int u = edge[i].v;
            if(depth[u] == depth[s] + 1 && edge[i].f > 0){
                int k = dfs(u, min(a, edge[i].f));
                if(k > 0){
                    flow += k, a -= k, edge[i].f -= k, edge[i^1].f += k, to[s] = u;
                    if(s != 0) vis[u - n] = true;
                }
            }
            if(!a) break;
        }
        if(a) depth[s] = -1;
        return flow;
    }
    
    int dinic(){
        int ret = 0;
        while(bfs()){
            ret += dfs(0, INF);
        }
        return ret;
    }
    
    int main(){
    
        full(head, -1);
        n = read(), m = read();
        for(int i = 1; i <= n; i ++)
            addEdge(0, i, 1), addEdge(i + n, 2 * n + 1, 1);
        for(int i = 0; i < m; i ++){
            int u = read(), v = read();
            addEdge(u, v + n, 1);
        }
        int ans = n - dinic();
        for(int i = 1; i <= n; i ++){
            if(!vis[i]){
                int cur = i;
                printf("%d ", cur);
                while(to[cur] != 2 * n + 1 && to[cur] != 0){
                    printf("%d ", to[cur] - n), cur = to[cur] - n;
                }
                puts("");
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    centos crash debug
    go get Unknown SSL protocol error in connection to gopkg.in
    Tensorflow serving with Kubernetes
    Spring 集成 Swagger UI
    Docker Registry V2 Garbage Collection
    Docker Registry V2 with Nginx
    Zabbix磁盘性能监控
    Zabbix CPU utilization监控参数
    Windows挂载Gluster复制卷
    Redis持久化存储(三)
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/10674011.html
Copyright © 2011-2022 走看看