• hiho# 1394最小路径覆盖 网络流拆点


    题目传送门

    思路:

      观察到路径上除了终点起点以外的每个点出度和入度都为1,和网络流的拆点很像,所以就把每个点都拆成两个点,若存在一条路径$(u,v)$,则建一条$(u,v+n,1)$的边,然后求出最大流后,每个起点的入度都是0,所以$ans=n-maxflow$。

      注意由于是拆点,所以各种数组都要开两倍空间。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    
    typedef long long ll;
    
    const ll INFLL = 0x3f3f3f3f3f3f3f3f;
    const int INF = 0x3f3f3f3f;
    const int maxn = 510;
    
    struct Edge {
        int to, flow, nxt;
        Edge(){}
        Edge(int to, int nxt, int flow):to(to),nxt(nxt), flow(flow){}
    }edge[maxn * maxn * 2];
    
    int head[maxn*2], dep[maxn*2];
    int S, T;
    int N, n, m, tot;
    void init(int n)
    {
        N=n;
        for (int i = 0; i <= N; ++i) head[i] = -1;
        tot = 0;
    }
    
    void addv(int u, int v, int w, int rw = 0)
    {
        edge[tot] = Edge(v, head[u], w); head[u] = tot++;
        edge[tot] = Edge(u, head[v], rw); head[v] = tot++;
    }
    
    bool BFS()
    {
        for (int i = 0; i <= N; ++i) dep[i] = -1;
        queue<int>q;
        q.push(S);
        dep[S] = 1;
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            for (int i = head[u]; ~i; i = edge[i].nxt)
            {
                
                if (edge[i].flow && dep[edge[i].to] == -1)
                {
                    dep[edge[i].to] = dep[u] + 1;
                    q.push(edge[i].to);
                }
            }
        }
        return dep[T] < 0 ? 0 : 1;
    }
    
    int DFS(int u, int f)
    {
        if (u == T || f == 0) return f;
        int w, used = 0;
        for (int i = head[u]; ~i; i = edge[i].nxt)
        {
            if (edge[i].flow && dep[edge[i].to] == dep[u] + 1)
            {
                w = DFS(edge[i].to, min(f - used, edge[i].flow));
                edge[i].flow -= w;
                edge[i ^ 1].flow += w;
                used += w;
                if (used == f) return f;
            }
        }
        if (!used) dep[u] = -1;
        return used;
    }
    
    int Dicnic()
    {
        int ans = 0;
        while (BFS())
        {
            ans += DFS(S, INF);
        }
        return ans;
    }
    
    int main(){
        cin>>n>>m;
        T=2*n+1;
        init(T);
        S=0;
        while(m--){
            int u,v;
            scanf("%d%d",&u,&v);
            addv(u,v+n,1);
        }
        for(int i=1;i<=n;i++){
            addv(S,i,1);
            addv(i+n,T,1);
        }
        int ans=n-Dicnic();
        printf("%d
    ",ans);
    }
  • 相关阅读:
    通过Math.atan2计算角度 改变物体朝向
    table.sort 排序的问题
    shader 实现正旋波效果 水面波动效果
    第一篇碎碎心得
    ping 整理
    路由器
    C语言里如何读取位数据的某几位?
    ubunut命令
    基于SPIflash 的fatfs调试步骤
    makefile 学习总结--函数
  • 原文地址:https://www.cnblogs.com/mountaink/p/10670781.html
Copyright © 2020-2023  润新知