码迷,mamicode.com
首页 > 其他好文 > 详细

P2691 逃离

时间:2019-10-17 17:23:02      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:line   printf   nbsp   ret   main   图片   sign   gis   div   

这题是一个裸的网络流的题,但是本蒟蒻还是调试了半天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;
}

 

P2691 逃离

标签:line   printf   nbsp   ret   main   图片   sign   gis   div   

原文地址:https://www.cnblogs.com/dorbmon/p/11693261.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!