BZOJ 2229 [Zjoi2011]最小割

来源:互联网 发布:python anaconda 安装 编辑:程序博客网 时间:2024/05/29 11:06

最小割树

关于最小割树的详细内容和证明,请看【ZJOI2016 day2讲课 无向图最小割】,这个东西自己找吧,我就不发了。。。

默默摘抄一些Gusfield算法

fa[u]在u被枚举到之前表示u所属点集的代表点,枚举到之后表示u在最小割树上的父亲。初始时所有点都属于以1为代表点的点集。从2到|V|依次枚举u,把u所在点集以u和fa[u]为源和汇拆分,所有被分到u侧的点x把fa[x]修改为u。

注意枚举之后只能把fa[x]=u或fa[x]=fa[u]的x拿来改,即属于当前点集的拿来改。这是小细节,不然会挂很惨。。。

关于跑完一次最大流之后如何确定最小割:找出从S开始在残量网络上BFS到的点和没被BFS到的点,这两个点集之间就是最小割

#include<cstdio>#include<cstring>#include<algorithm>#define N 155#define M 3005using namespace std;namespace runzhe2000{    const int INF = 1<<29;    int n, m, ecnt = 1, last[N], cur[N], level[N], fa[N], fa_v[N], S, T, qx[N], arr[N*2], cnt[N*2];    struct edge{int next, to, flow;}e[M<<2];    void addedge(int a, int b, int c)    {        e[++ecnt] = (edge){last[a], b, c};        last[a] = ecnt;        e[++ecnt] = (edge){last[b], a, 0};        last[b] = ecnt;    }    void linkedge(int a, int b, int c)    {        e[++ecnt] = (edge){last[a], b, c};        last[a] = ecnt;        e[++ecnt] = (edge){last[b], a, c};        last[b] = ecnt;    }     int q[N], timer, vis[N];    bool bfs()    {        level[q[0] = S] = 1; vis[S] = ++timer;        for(int head=0, tail=1; head<tail; head++)        {            int x = q[head];            for(int i = last[x]; i; i = e[i].next)            {                int y = e[i].to;                if(vis[y] == timer || !e[i].flow) continue;                vis[y] = timer;                 level[y] = level[x] + 1;                if(y == T)return true;                q[tail++] = y;            }        }        return false;    }    int dfs(int x, int flow)    {        if(x == T)return flow;        int use = 0;        for(int &i = cur[x]; i; i = e[i].next)        {            int y = e[i].to;            if(level[y] != level[x] + 1)continue;            int w = dfs(y, min(e[i].flow, flow - use));            use += w;            e[i].flow -= w;            e[i^1].flow += w;            if(use == flow)return use;        }        return use;    }    int dinic()    {        int ret = 0;        while(bfs())        {            memcpy(cur, last, sizeof(last));            ret += dfs(S, INF);        }        return ret;    }    void restore()    {        for(int i = 2; i <= ecnt; i += 2)             e[i].flow += e[i^1].flow, e[i^1].flow = 0;    }    void dfs(int x, int v, int f)    {        cnt[v]++;        for(int i = last[x]; i; i = e[i].next)        {            int y = e[i].to;            if(y == f)continue;            dfs(y, min(v, e[i].flow), x);        }    }    void init()    {        ecnt = 1;        memset(last,0,sizeof(last));        memset(cnt,0,sizeof(cnt));    }    void main()    {        int kase;        scanf("%d",&kase);        for(; kase--; )        {            init();            scanf("%d%d",&n,&m);            for(int i = 1, a, b, c; i <= m; i++)            {                scanf("%d%d%d",&a,&b,&c);                addedge(a,b,c);                addedge(b,a,c);            }            for(int i = 1; i <= n; i++) fa[i] = 1;            for(int i = 2; i <= n; i++)            {                restore();                S = i;                T = fa[i];                fa_v[i] = dinic();                  for(int j = i+1; j <= n; j++) if(vis[j] == timer && fa[j] == fa[i]) fa[j] = i;            }            int Q, tot = 0;            scanf("%d",&Q);            for(int i = 1; i <= Q; i++) scanf("%d",&qx[i]), arr[++tot] = qx[i];            for(int i = 2; i <= n; i++) arr[++tot] = fa_v[i];            sort(arr+1,arr+1+tot);            tot = unique(arr+1,arr+1+tot) - arr - 1;            for(int i = 1; i <= Q; i++) qx[i] = lower_bound(arr+1,arr+1+tot,qx[i]) - arr;            for(int i = 2; i <= n; i++) fa_v[i] = lower_bound(arr+1,arr+1+tot,fa_v[i]) - arr;            memset(last,0,sizeof(last)); ecnt = 1;            for(int i = 2; i <= n; i++) linkedge(fa[i], i, fa_v[i]);            for(int i = 1; i <= n; i++) dfs(i, N*2-1, 0);            for(int i = 1; i < N*2; i++)            {                cnt[i] /= 2;                cnt[i] += cnt[i-1];            }            for(int i = 1; i <= Q; i++) printf("%d\n",cnt[qx[i]]);            puts("");        }    }}int main(){    runzhe2000::main();}
0 0
原创粉丝点击