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\n", 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\n", ans1);
    for(int i=0; i<nans; i++)
        printf("%d%c", ans[i], i==nans-1?‘\n‘:‘ ‘);
    return 0;
}
时间: 2024-08-08 00:34:14

USACO 5.4.3 点的最小割的相关文章

USACO 4.4.2 追查坏牛奶 oj1341 网络流最小割问题

描述 Description 你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶.很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网.这个送货网很大,而且关系复杂.你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径.送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶.在追查这些有三聚氰胺的牛奶的时候,有必要保证它不被送到零售商手里,所以必须使某些运输卡车停止运输,但是停止每辆卡车都会有一定的经济损失.你的

USACO 4.4 Pollutant Control (网络流求最小割割集)

Pollutant ControlHal Burch It's your first day in Quality Control at Merry Milk Makers, and already there's been a catastrophe: a shipment of bad milk has been sent out. Unfortunately, you didn't discover this until the milk was already into your del

USACO Section 5.4 TeleCowmunication(最小割)

挺裸的一道最小割.把每台电脑拆成一条容量为1的边,然后就跑最大流.从小到大枚举每台电脑,假如去掉后 最大流=之前最大流+1,那这台电脑就是answer之一了. -------------------------------------------------------------------------------------- #include<cstdio> #include<vector> #include<cstring> #define rep(i,r) f

【jzyzoj】【p1320 patrol】 巡逻(网络流最小割例题)

描述 Description FJ有个农场,其中有n块土地,由m条边连起来.FJ的养牛场在土地1,在土地n有个新开张的雪糕店.Bessie经常偷偷溜到雪糕店,当Bessie去的时候,FJ就要跟上她.但是Bessie很聪明,她在从雪糕店返回时不会经过去雪糕店时经过的农场,因此FJ总是抓不住Bessie.为了防止Bessie生病,FJ决定把一些诚实的狗放在一些土地(1和n除外)上,使Bessie无法在满足每块土地最多只经过一次的条件的情况下,从养牛场溜到雪糕店然后又溜回养牛场.求出FJ最少要放多少只

【BZOJ2039】【2009国家集训队】人员雇佣 [最小割]

人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j.当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得

hdoj 4289 Control 【拆点 求最小割】

Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2295    Accepted Submission(s): 961 Problem Description You, the head of Department of Security, recently received a top-secret informati

There is a war (hdu 2435 最小割+枚举)

There is a war Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 970    Accepted Submission(s): 277 Problem Description There is a sea. There are N islands in the sea. There are some directional

HDU 3657 Game(取数 最小割)经典

Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1065    Accepted Submission(s): 449 Problem Description onmylove has invented a game on n × m grids. There is one positive integer on each g

POJ2914 Minimum Cut【全局最小割】【Stoer-Wangner】

题目链接: http://poj.org/problem?id=2914 题目大意: 提一个无向有重边的图,有重边的边权累加起来,求全局最小割. 思路: 一个无向连通图,去掉一个边集可以使其变成两个连通分量则这个边集就是割集.最小割 集当然就是权和最小的割集. 这是一个最简单的全局最小割模板题.直接套上模板就可以了.来说说Stoer-Wangner算 法吧. Stoer-Wangner算法: 对于图中的任意两个顶点u和v,若u,v属于最小割的同一个集合中,那么僵顶点u和顶点 v合并后并不影响图的