ACM/ICPC 之 Dinic+枚举最小割点集(可做模板)(POJ1815)

   最小割的好题,可用作模板。

//Dinic+枚举字典序最小的最小割点集
//Time:1032Ms   Memory:1492K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;

#define MAXN 205
#define INF 0x3f3f3f3f

int N, S, T;
int s,t;
int sres[2*MAXN][2*MAXN];   //source-res
int res[2*MAXN][2*MAXN];
int d[2*MAXN];
int cut[MAXN];  //最小割点集
bool v[2*MAXN];

bool bfs()
{
    memset(d, -1, sizeof(d));
    queue<int> q;
    q.push(s);  d[s] = 0;
    while(!q.empty() && d[t] == -1){
        int cur = q.front();    q.pop();
        for(int i = 1; i <= t; i++)
        {
            if(d[i] == -1 && res[cur][i])
            {
                d[i] = d[cur] + 1;
                q.push(i);
            }
        }
    }
    return d[t] != -1;
}

int dfs(int x, int sum)
{
    if(x == t || sum == 0)  return sum;
    int src = sum;
    for(int i = 1; i <= t; i++)
    {
        if(d[i] == d[x] + 1 && res[x][i])
        {
            int tmp = dfs(i, min(sum, res[x][i]));
            res[x][i] -= tmp;
            res[i][x] += tmp;
            sum -= tmp;
        }
    }
    return src - sum;
}

int Dinic()
{
    memcpy(res, sres, sizeof(sres));
    int maxFlow = 0;
    while(bfs())
        maxFlow += dfs(s,INF);
    return maxFlow;
}

int main()
{
    //freopen("in.txt", "r", stdin);

    while(~scanf("%d%d%d", &N,&S,&T))
    {
        memset(sres, 0 ,sizeof(sres));
        s = 0;  t = 2*N+1;
        sres[0][S] = sres[T+N][t] = INF;
        for(int i = 1; i <= N; i++)
        {
            sres[i][i + N] = 1;
            for(int j = 1; j <= N; j++)
            {
                int num;
                scanf("%d", &num);
                if(num && i != j) sres[i+N][j] = INF;
            }
        }
        sres[S][S+N] = sres[T][T+N] = INF;
        int ans = Dinic();
        if(ans == INF){ //不可分开
            printf("NO ANSWER!\n");
            continue;
        }
        else {
            printf("%d\n", ans);
            if(ans == 0) continue;  //已经分开
        }

        //枚举最小割点集
        int len = 0, tmp = ans;
        for(int i = 1; i <= N && tmp; i++)
        {
            if(i == S || i == T)   continue;
            if(res[i][i+N])    continue;
            sres[i][i+N] = 0;
            int k = Dinic();
            if(k != tmp){
                tmp = k;
                cut[len++] = i;
            }
            else sres[i][i+N] = 1;
        }
        for(int i = 0; i < ans - 1; i++)
            printf("%d ", cut[i]);
        printf("%d\n", cut[ans-1]);
    }

    return 0;
}
时间: 2024-08-30 00:37:53

ACM/ICPC 之 Dinic+枚举最小割点集(可做模板)(POJ1815)的相关文章

hdu 4289 网络流拆点,类似最小割(可做模板)邻接矩阵实现

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

poj--1815--Friendship(最小割点集)(枚举求最小字典序)

 Friendship Time Limit: 2000MS   Memory Limit: 20000KB   64bit IO Format: %I64d & %I64u Submit Status Description In modern society, each person has his own friends. Since all the people are very busy, they communicate with each other only by phone

ACM/ICPC 之 机器调度-匈牙利算法解最小点覆盖集(DFS)(POJ1325)

//匈牙利算法-DFS //求最小点覆盖集 == 求最大匹配 //Time:0Ms Memory:208K #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define MAX 105 #define INF 0x3f3f3f3f int n,m,k; int gp[MAX][MAX]; bool sx[MAX],s

最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583)

Question 例题3-5 最小生成元 (Digit Generator, ACM/ICPC Seoul 2005, UVa1583) 如果x+x的各个数字之和得到y,就是说x是y的生成元.给出n(1<=n<=100000), 求最小生成元.无解输出0.例如,n=216,121,2005时的解分别是198,0,1979. Think 方法一:假设所求生成元记为m,不难发现m<n.换句话说,只需枚举所有的m<n,看看有木有哪个数是n的生成元.此举效率不高,因为每次计算一个n的生成元

HDU 5889 Barricade 【BFS+最小割 网络流】(2016 ACM/ICPC Asia Regional Qingdao Online)

Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 997    Accepted Submission(s): 306 Problem Description The empire is under attack again. The general of empire is planning to defend his

BZOJ 1050 旅行comf(枚举最小边-并查集)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1050 题意:给出一个带权图.求一条s到t的路径使得这条路径上最大最小边的比值最小? 思路:将边排序.枚举最小边,然后将边一个一个插到并查集里,s和t联通时计算更新答案. struct node { int u,v,w; void get() { RD(u,v,w); } }; int cmp(node a,node b) { return a.w<b.w; } int n,m,s,t;

(并查集)Travel -- hdu -- 5441(2015 ACM/ICPC Asia Regional Changchun Online )

http://acm.hdu.edu.cn/showproblem.php?pid=5441 Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2061    Accepted Submission(s): 711 Problem Description Jack likes to travel around the wo

【题解】 2015 ACM/ICPC Asia Regional Shenyang Online

[1006] FangFang (暴力枚举) Fang Fang Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 871    Accepted Submission(s): 364 Problem Description Fang Fang says she wants to be remembered. I promise her.

《ACM/ICPC 算法训练教程》读书笔记一之数据结构(堆)

书籍简评:<ACM/ICPC 算法训练教程>这本书是余立功主编的,代码来自南京理工大学ACM集训队代码库,所以小编看过之后发现确实很实用,适合集训的时候刷题啊~~,当时是听了集训队final的意见买的,感觉还是不错滴. 相对于其他ACM书籍来说,当然如书名所言,这是一本算法训练书,有着大量的算法实战题目和代码,尽管小编还是发现了些许错误= =,有部分注释的语序习惯也有点不太合我的胃口.实战题目较多是比较水的题,但也正因此才能帮助不少新手入门,个人认为还是一本不错的算法书,当然自学还是需要下不少