P2691 逃离

烈酒焚心 提交于 2019-12-01 16:31:57

这题是一个裸的网络流的题,但是本蒟蒻还是调试了半天2333.总是犯低级错误。

一开始我是用EK算法实现的。结果如下:

 

 然后我又用Dinic算法实现了一下。

 

 发现更慢了2333.我也不知道为啥,按道理Dinic应该比EK快的不知道到哪里去了才对。

下面是我的代码实现:
EK算法:

#include <bits/stdc++.h>
using namespace std;

#define re register
inline long long read() {
    char ch = getchar(); long long x = 0, f = 1;
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    } while('0' <= ch && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    } return x * f;
}
const int N = 36000,M = 5000000;
struct line {
    int v;
    int cap;
    int nxt;
} datas [M];
int head [N],cnt = 1;
inline void add (int a,int b,int c) {
    ++ cnt;
    datas [cnt].v = b;
    datas [cnt].cap = c;
    datas [cnt].nxt = head [a];
    head [a] = cnt;
}
int s = 0,t;
int n,m;
inline int qlink (int x,int y) {
    //前部点 
    return x * n + y;
}
inline int hlink (int x,int y) {    //后部点 
    return qlink (n,n) + qlink (x,y);
}
int dx [] = {0,0,1,-1},dy [] = {1,-1,0,0};
bool vis [N];
inline int dfs (int u,int flow) {
    vis [u] = true;
    //开始EK算法
    if (u == t) {
        return flow;
    }
    for (int ptr = head [u];ptr;ptr = datas [ptr].nxt) {
        int v = datas [ptr].v,c = datas [ptr].cap;
        if (!c || vis [v]) {
            continue ;
        }
        int ret = dfs (v,min (flow,c));
        if (!ret) {
            continue ;
        }
        //开始减掉自己
        datas [ptr].cap -= ret;
        datas [ptr ^ 1].cap += ret; 
        return ret;
    }
    return 0;
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen ("shit.txt","r",stdin);
#endif 
#ifdef ONLINE_JUDGE
#endif
    n = read (),m = read ();
    t = hlink (n,n) + 1;
    for (int i = 1;i <= n;++ i) {
        for (int j = 1;j <= n;++ j) {
            add (qlink (i,j),hlink (i,j),1);
            add (hlink (i,j),qlink (i,j),0);
        }
    }
    for (int i = 1;i <= m;++ i) {
        int x = read (),y = read ();
        //开始连接到源点
        add (s,qlink (x,y),1);
        add (qlink (x,y),s,0);
    }
    //开始连接周围的点
    for (int i = 1;i <= n;++ i) {
        for (int j = 1;j <= n;++ j) {
            for (int k = 0;k < 4;++ k) {
                int x = i + dx [k],y = j + dy [k];
                if (x < 1 || y < 1 || x > n || y > n) {
                    continue ;
                }
                add (hlink (i,j),qlink (x,y),1);
                add (qlink (x,y),hlink (i,j),0);
            }
        }
    }
    //开始连接周围的点
    for (int i = 1;i <= n;++ i) {
        add (hlink (i,1),t,1);
        add (t,hlink (i,1),0);
        
        add (hlink (1,i),t,1);
        add (t,hlink (1,i),0);
        
        add (hlink (n,i),t,1);
        add (t,hlink (n,i),0);
        
        add (hlink (i,n),t,1);
        add (t,hlink (i,n),0);
    } 
    int t = 0;
    int ans = 0;
    while (t = dfs (s,0x3f3f3f3f)) {
        ans += t;
        memset (vis,false,sizeof vis);
    }
    if (ans >= m) {
        printf ("YES\n");
    }else {
        printf ("NO\n");
    }
    return 0;
}

下面是Dinic算法

#include <bits/stdc++.h>
using namespace std;

#define re register
inline long long read() {
    char ch = getchar(); long long x = 0, f = 1;
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    } while('0' <= ch && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    } return x * f;
}
const int N = 36000,M = 5000000;
struct line {
    int v;
    int cap;
    int nxt;
} datas [M];
int head [N],cnt = 1;
inline void add (int a,int b,int c) {
    ++ cnt;
    datas [cnt].v = b;
    datas [cnt].cap = c;
    datas [cnt].nxt = head [a];
    head [a] = cnt;
}
int s = 0,t;
int n,m;
inline int qlink (int x,int y) {
    //前部点 
    return x * n + y;
}
inline int hlink (int x,int y) {    //后部点 
    return qlink (n,n) + qlink (x,y);
}
int dx [] = {0,0,1,-1},dy [] = {1,-1,0,0};
int d [N];
bool vis [N];
inline bool dinic () {
    memset (d,0,sizeof d);
    queue<int> q;q.push (s);
    d [s] = 1;
    while (!q.empty ()) {
        int u = q.front ();q.pop ();
        for (int ptr = head [u];ptr;ptr = datas [ptr].nxt) {
            int v = datas [ptr].v;
            if (!d [v] && datas [ptr].cap) {
                q.push (v);
                d [v] = d [u] + 1;
            }
        }
    }
    return d [t];
}
int dfs (int u,int flow) {
    if (u == t) {
        return flow;
    }
    int dd = 0;
    for (int ptr = head [u];ptr;ptr = datas [ptr].nxt) {
        int v = datas [ptr].v,cap = datas [ptr].cap;
        if (d [v] == d [u] + 1 && cap) {
            int ret = dfs (v,min (cap,flow));
            datas [ptr].cap -= ret;
            datas [ptr ^ 1].cap += ret;
            flow -= ret;
            dd += ret;
            if (!flow) {
                break ;
            }
            
        }
    }
    if (!dd) {
        d [u] = -1;
    }
    return dd;
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen ("shit.txt","r",stdin);
#endif 
#ifdef ONLINE_JUDGE
#endif
    n = read (),m = read ();
    t = hlink (n,n) + 1;
    for (int i = 1;i <= n;++ i) {
        for (int j = 1;j <= n;++ j) {
            add (qlink (i,j),hlink (i,j),1);
            add (hlink (i,j),qlink (i,j),0);
        }
    }
    for (int i = 1;i <= m;++ i) {
        int x = read (),y = read ();
        //开始连接到源点
        add (s,qlink (x,y),1);
        add (qlink (x,y),s,0);
    }
    //开始连接周围的点
    for (int i = 1;i <= n;++ i) {
        for (int j = 1;j <= n;++ j) {
            for (int k = 0;k < 4;++ k) {
                int x = i + dx [k],y = j + dy [k];
                if (x < 1 || y < 1 || x > n || y > n) {
                    continue ;
                }
                add (hlink (i,j),qlink (x,y),1);
                add (qlink (x,y),hlink (i,j),0);
            }
        }
    }
    //开始连接周围的点
    for (int i = 1;i <= n;++ i) {
        add (hlink (i,1),t,1);
        add (t,hlink (i,1),0);
        
        add (hlink (1,i),t,1);
        add (t,hlink (1,i),0);
        
        add (hlink (n,i),t,1);
        add (t,hlink (n,i),0);
        
        add (hlink (i,n),t,1);
        add (t,hlink (i,n),0);
    } 
    int t = 0;
    int ans = 0;
    while (dinic ()) {
        ans += dfs (s,0x3f3f3f3f);
    }
    if (ans >= m) {
        printf ("YES\n");
    }else {
        printf ("NO\n");
    }
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!