[网络流]SPOJ962 Intergalactic Map

来源:互联网 发布:ubuntu flash 安装 编辑:程序博客网 时间:2024/06/10 06:19

题意

有一个无向图,求是否能够不重复经过一个点地从1走到2再走到3

思路

首先,可以想到利用网络流来求解,建图的时候,把每一个点拆成两个点,之间连一条容量为1的弧
然后根据原图将每一条弧加入到网络中,注意是像PiPj来加边
但是要注意一点,因为是从1走到2再走到3,显然这是很难做的,那么可以换一个思路,假设不是从1走到2再走到3,而是从2开始,不重复经过一个点,走到1和3
这样,构图和求解都变得简单起来了。
从s连一条容量为2的边到2,然后分别从1和3各连一条边到t,做一次最大流,如果最大流为2,那么就有这样的路径,反之没有
可以发现,SPOJ上的题大多数对于空间的限制几乎为没有:1.5G
(这么大哪里用得完,开10000×10000的int数组都可以)
但是,时间非常严格,0.5s都不到?
而且这一道题数据量很大,结果过了?而且只用了80ms?Excuse me?其实刚做的时候觉得Dinic可能过不了,结果过了,说不定用ISAP或者预流推进会更快

代码

#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int MAXN = 70111,          MAXM = 603333,           INF = 0x3f3f3f3f;struct Edge {    int to, cap, flow, _next;    Edge() {        to = cap = flow = _next = 0;    }};struct Dinic {    int n, m, s, t;    Edge e[MAXM];    int head[MAXN];    int d[MAXN];    int cur[MAXN];    void init() {        memset(head, -1, sizeof head);        m = 0;    }    void AddEdge(int from, int to, int cap) {        e[m].to = to;        e[m].cap = cap;        e[m]._next = head[from];        e[m].flow = 0;        head[from] = m++;        e[m].to = from;        e[m].cap = 0;        e[m]._next = head[to];        e[m].flow = 0;        head[to] = m++;    }    bool BFS() {        memset(d, 0, sizeof d);        std :: queue < int > Q;        Q.push(s);        while(!Q.empty()) {            int x = Q.front();            Q.pop();            for(int i = head[x]; i != -1; i = e[i]._next) {                if(!d[e[i].to] && e[i].to != s && e[i].cap > e[i].flow) {                    d[e[i].to] = d[x] + 1;                    Q.push(e[i].to);                }            }         }         return d[t];    }    int DFS(int x, int a) {        if(x == t || a == 0) {            return a;        }        int flow = 0, f;        for(int& i = cur[x]; i != -1; i = e[i]._next) {            if(d[e[i].to] == d[x] + 1 && (f = DFS(e[i].to, min(a, e[i].cap - e[i].flow))) > 0) {                e[i].flow += f;                e[i ^ 1].flow -= f;                flow += f;                a -= f;                if(a == 0) {                    break;                }            }        }        return flow;    }    int Maxflow(int s, int t) {        this -> s = s;        this -> t = t;        int flow = 0;        while(BFS()) {            memmove(cur, head, sizeof head);             flow += DFS(s, INF);        }        return flow;    }} dinic;void solve() {    int n, m;    scanf("%d%d", &n, &m);    dinic.init();    for(int i = 0; i < m; ++i) {        int u, v;        scanf("%d%d", &u, &v);        if (u < 1 || u > n || v < 1 || v > n) {            continue;          }        dinic.AddEdge(u + n, v, 1);        dinic.AddEdge(v + n, u, 1);    }    const int t = 2 * n + 1;    dinic.AddEdge(0, 2 + n, 2);    dinic.AddEdge(1, t, 1);    dinic.AddEdge(3, t, 1);    for(int i = 4; i <= n; ++i) {        dinic.AddEdge(i, i + n, 1);    }    if(dinic.Maxflow(0, t) == 2) {        printf("YES\n");    } else {        printf("NO\n");    }}int main() {    int t;    scanf("%d", &t);    while(t--) {        solve();    }    return 0;} 
0 0
原创粉丝点击