• USACO 5.4.3 点的最小割


      这道题的难点在于将点拆分, 无向图变为有向图, 对于 i点我们可以将这个点拆分成2*i-1 -> 2*i,权值为1 对于i - j, 我们可以将点拆分以后再添加2*j -> 2*i-1 2*i -> 2*j-1,权值为inf,  然后求解最大流即为要去掉的顶点的个数, 求解具体的边的时候我们可以枚举要删除的边, 假设删除前的最大流为f,边权为1, 删除边后的最大流为ff, 若ff+1 == f的话那么这条边就在最小割集中。然后更新最大流,删掉最这条边重复上述操作即可, 代码如下:

    /*
        ID: m1500293
        LANG: C++
        PROG: telecow
    */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    const int maxn = 250;
    int inf = 0x3f3f3f3f;
    struct Dinic
    {
        int n;   //n个顶点
        struct edge { int from, to, cap; };
        vector<int> G[maxn];
        vector<edge> e;
        int level[maxn], iter[maxn];
        void init()
        {
            for(int i=0; i<=n; i++)
                G[i].clear();
            e.clear();
        }
        void add_edge(int u, int v, int cap)
        {
            e.push_back((edge){u, v, cap});
            e.push_back((edge){v, u, 0});
            int m = e.size();
            G[u].push_back(m-2);
            G[v].push_back(m-1);
        }
        void bfs(int s)
        {
            memset(level, -1, sizeof(level));
            queue<int> que;
            level[s] = 0;
            que.push(s);
            while(!que.empty())
            {
                int u = que.front();
                que.pop();
                for(int i=0; i<G[u].size(); i++)
                {
                    edge &te = e[G[u][i]];
                    if(te.cap>0 && level[te.to]<0)
                    {
                        level[te.to] = level[u] + 1;
                        que.push(te.to);
                    }
                }
            }
        }
        int dfs(int v, int t, int f)
        {
            if(v == t) return f;
            for(int &i=iter[v]; i<G[v].size(); i++)
            {
                edge &tpe = e[G[v][i]];
                if(tpe.cap>0 && level[v]<level[tpe.to])
                {
                    int d = dfs(tpe.to, t, min(f, tpe.cap));
                    if(d > 0)
                    {
                        tpe.cap -= d;
                        e[G[v][i]^1].cap += d;
                        return d;
                    }
                }
            }
            return 0;
        }
        int max_flow(int s, int t)
        {
            int flow = 0;
            for(;;)
            {
                bfs(s);
                if(level[t]<0) return flow;
                memset(iter, 0, sizeof(iter));
                int f;
                while((f=dfs(s, t, 0x3fffffff)>0))
                    flow += f;
            }
        }
    }aa, bb;
    bool cmp(const int &a, const int &b)
    {
        return a < b;
    }
    int ans[200], nans;
    int main()
    {
        freopen("telecow.in", "r", stdin);
        freopen("telecow.out", "w", stdout);
        int N, M, c1, c2;
        scanf("%d%d%d%d", &N, &M, &c1, &c2);
        aa.n = 2*N;
        aa.init();
    
        for(int i=0; i<M; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            aa.add_edge(2*u, 2*v-1, inf);
            aa.add_edge(2*v, 2*u-1, inf);
    //        aa.add_edge(2*u-1, 2*u, 1);
    //        aa.add_edge(2*v-1, 2*v, 1);           //会导致重复添加一条边
        }
        for(int i=1; i<=N; i++)
            aa.add_edge(2*i-1, 2*i, 1);
        //printf("%d
    ", aa.max_flow(2*c1, 2*c2-1));
        bb = aa;
        int f = bb.max_flow(2*c1, 2*c2-1);
        int ans1 = f;
        nans = 0;
        for(int i=0; i<aa.e.size(); i++) if(aa.e[i].cap == 1)
        {
            bb = aa;
            bb.e[i].cap = 0;
            int ff = bb.max_flow(2*c1, 2*c2-1);
            if(ff+1 == f)   //这条边在最小割中
            {
                ans[nans++] = bb.e[i].to/2;
                f -= 1;    //更新最大流
                aa.e[i].cap = 0;    //删掉这条边
            }
        }
        sort(ans, ans+nans, cmp);
        printf("%d
    ", ans1);
        for(int i=0; i<nans; i++)
            printf("%d%c", ans[i], i==nans-1?'
    ':' ');
        return 0;
    }
  • 相关阅读:
    只需 4 步,手把手教你如何实现滤镜功能
    paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制
    socket网络编程的一些基础知识
    图像处理、模式识别、模式分类、机器视觉推荐图书
    数据挖掘、机器学习和模式识别关系与区别
    Qt4_VS10 程序打包发布
    Qt之多线程
    QT中.pro文件的写法
    高斯定理的证明
    《Linear Algebra and Its Applications》-chaper3-行列式-行列式初等变换
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5185088.html
Copyright © 2020-2023  润新知