HDU 4280 网络流(ISAP || Dinic)

来源:互联网 发布:连接其它机器的mysql 编辑:程序博客网 时间:2024/05/17 05:47

题目链接

网络流裸题,不过第一发写的 dinic + 当前弧优化果断超时,后来加了扩栈指令9000多ms险过,本题让我真正意识到了只掌握Dinic写法的局限性,所以学习了很久ISAP的写法,通过研究鸟神当年的博客,终于算是基本掌握qwq

鸟神的ISAP模板

写完试了一下 3000ms过掉,贴上我自己的模板

// ISAP + 当前弧优化 + GAP优化#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;const int INF = 1e9 + 7;const int A   = 1e5 + 10;class Edge{public:    int v,w,next;}G[A<<1];int head[A],cur[A],dis[A],num[A],que[A],pre[A];int st,ed,nv,tot,Thead,Ttail;void add(int u,int v,int w){    G[tot].v = v;    G[tot].w = w;    G[tot].next = head[u];    head[u] = tot++;    swap(u,v);    G[tot].v = v;    G[tot].w = w;    G[tot].next = head[u];    head[u] = tot++;}void init(){    tot = 0;    memset(head,-1,sizeof(head));}void Rev_bfs(){    memset(dis,-1,sizeof(dis));    memset(num,0,sizeof(num));    num[0]++;    dis[ed] = 0;    Thead = Ttail = 0;    que[Ttail++] = ed;    while(Thead < Ttail){        int u = que[Thead++];        for(int i=head[u] ;i!=-1 ;i=G[i].next){            int v = G[i].v;            if(dis[v] == -1){                dis[v] = dis[u] + 1;                num[dis[v]]++;                que[Ttail++] = v;            }        }    }}int ISAP(){    memcpy(cur,head,sizeof(cur));    Rev_bfs();    int flow = 0,u = pre[st] = st;    while(dis[st] < nv){       // printf("!");        if(u == ed){            int f = INF,neck;            for(int i=st ;i!=ed ;i=G[cur[i]].v){                if(f > G[cur[i]].w){                    f = G[cur[i]].w;                    neck = i;                }            }            for(int i=st ;i!=ed ;i=G[cur[i]].v){                G[cur[i]].w -= f;                G[cur[i]^1].w += f;            }            flow += f;            u = neck;        }        bool flag = 0;        for(int i=cur[u] ;i!=-1 ;i=G[i].next){            int v = G[i].v,w = G[i].w;            if(dis[u] == dis[v]+1 && w){                flag = 1;                cur[u] = i;                pre[v] = u;                u = v;                break;            }        }        if(!flag){            if((--num[dis[u]]) == 0) break;            int mind = nv;            for(int i=head[u] ;i!=-1 ;i=G[i].next){                int v = G[i].v,w = G[i].w;                if(w && mind > dis[v]){                    cur[u] = i;                    mind = dis[v];                }            }            dis[u] = mind + 1;            num[dis[u]]++;            u = pre[u];        }    }    return flow;}int main(){    //freopen("input","r",stdin);    int T;    scanf("%d",&T);    while(T--){        init();        int n,m;        scanf("%d%d",&n,&m);        int Min = INF,Max =-INF;        for(int i=1 ;i<=n ;i++){            int x,y;            scanf("%d%d",&x,&y);            if(x<Min){                Min = x;st = i;            }            if(x>Max){                Max = x;ed = i;            }        }        nv = n  + 1;        for(int i=1 ;i<=m ;i++){            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            add(u,v,w);        }        printf("%d\n",ISAP());    }    return 0;}