HDU 3046 Pleasant sheep and big big wolf(SAP,Dinic模板)

来源:互联网 发布:linux curl get请求 编辑:程序博客网 时间:2024/06/06 03:20

题目地址
题意:狼要吃羊,1的位置是羊的位置,2的位置是狼的位置,0是你可以放栅栏的位置,如果羊被栅栏围到了则狼就吃不掉羊了。问要用的栅栏最少是多少?
思路:让狼与源点连,羊与汇点连,可以立栅栏的位置与周围连上一条容量为1的边,这样就转化为最小割的问题了。只要源点和汇点不连通了就隔离开来了。因为是模板题,我用了两种方法写。
Dinic:

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 50000#define M 1000000#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;int head[N], level[N];int n, m, cnt;struct node {    int to;    int cap;//剩余流量    int next;}edge[2 * M];int mapp[210][210];int dir[4][2] = { { 1,0 },{ 0,1 },{ -1,0 },{ 0,-1 } };bool check(int x, int y) {// 判断是否越界    if (x >= 0 && x < n && y >= 0 && y < m)        return true;    return false;}struct Dinic {    void init() {        memset(head, -1, sizeof(head));        cnt = 0;    }    void add(int u, int v, int cap) {//有向图        edge[cnt].to = v, edge[cnt].cap = cap, edge[cnt].next = head[u], head[u] = cnt++;        edge[cnt].to = u, edge[cnt].cap = 0, edge[cnt].next = head[v], head[v] = cnt++;//反向边    }    bool bfs(int s, int t) {//建立分层图        memset(level, -1, sizeof(level));        queue<int>q;        level[s] = 0;//源点的层次最高        q.push(s);        while (!q.empty()) {            int u = q.front();            q.pop();            for (int i = head[u]; i != -1; i = edge[i].next) {                int v = edge[i].to;                if (edge[i].cap > 0 && level[v] < 0) {                    level[v] = level[u] + 1;                    q.push(v);                    if (v == t) {                        return true;                    }                }            }        }        return false;    }    int dfs(int u, int t, int num) {//找增广路        if (u == t || num == 0) {//找到了汇点返回当前的最小值,在这条路径上分别减去最小值            return num;        }        int ans = num;        for (int i = head[u]; i != -1; i = edge[i].next) {            int v = edge[i].to;            if (edge[i].cap > 0 && level[u] < level[v]) {                int d = dfs(v, t, min(num, edge[i].cap));                ans -= d;                edge[i].cap -= d;                edge[i ^ 1].cap += d;//反向边加值                if (ans == 0)return num;            }        }        return num - ans;    }    int dinic(int s, int t) {//源点和汇点        int sum = 0, num;        while (bfs(s, t)) {            sum += dfs(s, t, inf);        }        return sum;    }}DC;int main() {    cin.sync_with_stdio(false);    int Case = 1;    while (cin >> n >> m) {        DC.init();        for (int i = 0; i < n; i++) {            for (int j = 0; j < m; j++) {                cin >> mapp[i][j];            }        }        int s = n*m;        int t = n*m + 1;        for (int i = 0; i < n; i++) {            for (int j = 0; j < m; j++) {                int pos = i*m + j;                if (mapp[i][j] == 1) {                    DC.add(pos, t, inf);                }                else if (mapp[i][j] == 2) {                    DC.add(s, pos, inf);                }                for (int k = 0; k < 4; k++) {                    int x = i + dir[k][0];                    int y = j + dir[k][1];                    if (check(x, y)) {                        DC.add(pos, x*m + y, 1);                    }                }            }        }        cout << "Case " << Case++ << ":" << endl;        cout << DC.dinic(s, t) << endl;    }    return 0;}

SAP:

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 40010#define M 800010#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1000000007;int mapp[210][210];int head[N];int n, m, cnt;struct node {    int to;    int cap;//剩余流量    int next;}edge[2 * M];//因为加了正反两条边,所以要乘二bool vis[N];int len[N];int gap[N];int pre[N];int curedge[N];int dir[4][2] = { { 1,0 },{ 0,1 },{ -1,0 },{ 0,-1 } };bool check(int x, int y) {// 判断是否越界    if (x >= 0 && x < n && y >= 0 && y < m)        return true;    return false;}struct Sap {    void init() {        memset(head, -1, sizeof(head));        cnt = 0;    }    void add(int u, int v, int cap) {//有向图        edge[cnt].to = v, edge[cnt].cap = cap, edge[cnt].next = head[u], head[u] = cnt++;        edge[cnt].to = u, edge[cnt].cap = 0, edge[cnt].next = head[v], head[v] = cnt++;//反向边    }    int max_flow(int s, int t, int n){//n为总点数个数        int cur_flow = 0, flow_ans = 0, i, u, neck, tmp;        memset(len, 0, sizeof(len));        memset(gap, 0, sizeof(gap));        memset(pre, -1, sizeof(pre));        for (i = 0; i <= n; i++)            curedge[i] = head[i];        gap[0] = n + 1;        u = s;        while (len[s] < n + 1) {            if (u == t) {                cur_flow = inf;                for (i = s; i != t; i = edge[curedge[i]].to) {                    if (cur_flow > edge[curedge[i]].cap)                        cur_flow = edge[curedge[i]].cap, neck = i;                }                for (i = s; i != t; i = edge[curedge[i]].to)                {                    tmp = curedge[i];                    edge[tmp].cap -= cur_flow;                    edge[tmp ^ 1].cap += cur_flow;                }                flow_ans += cur_flow;                u = neck;            }            for (i = curedge[u]; i != -1; i = edge[i].next)                if (edge[i].cap&&len[u] == len[edge[i].to] + 1)                    break;            if (i != -1) {                curedge[u] = i;                pre[edge[i].to] = u;                u = edge[i].to;            }            else {                if (0 == --gap[len[u]])                    break;                curedge[u] = head[u];                for (tmp = n + 5, i = head[u]; i != -1; i = edge[i].next)                    if (edge[i].cap)                        tmp = min(tmp, len[edge[i].to]);                len[u] = tmp + 1;                ++gap[len[u]];                if (u != s)                    u = pre[u];            }        }        return flow_ans;    }}sap;int main() {    cin.sync_with_stdio(false);    int Case = 1;    while (cin >> n >> m) {        sap.init();        for (int i = 0; i < n; i++) {            for (int j = 0; j < m; j++) {                cin >> mapp[i][j];            }        }        int s = n*m;        int t = n*m + 1;        for (int i = 0; i < n; i++) {            for (int j = 0; j < m; j++) {                int pos = i*m + j;                if (mapp[i][j] == 1) {                    sap.add(pos, t, inf);                }                else if (mapp[i][j] == 2) {                    sap.add(s, pos, inf);                }                for (int k = 0; k < 4; k++) {                    int x = i + dir[k][0];                    int y = j + dir[k][1];                    if (check(x, y)) {                        sap.add(pos, x*m + y, 1);                    }                }            }        }        cout << "Case " << Case++ << ":" << endl;        cout<< sap.max_flow(s, t, t) << endl;    }    return 0;}
阅读全文
0 0
原创粉丝点击