zoukankan      html  css  js  c++  java
  • [bzoj2229][Zjoi2011]最小割

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割。 对于带权图来说,将所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而s,t的最小割指的是在关于s,t的割中容量最小的割” 现给定一张无向图,小白有若干个形如“图中有多少对点它们的最小割的容量不超过x呢”的疑问,小蓝虽然很想回答这些问题,但小蓝最近忙着挖木块,于是作为仍然是小蓝的好友,你又有任务了。

    T<=10,n<=150,m<=3000,q<=30

    最小割树(分治+最小割)

    每次从要分治的部分中选出两个点求最小割,并且更新与S相连的部分的点和与T相连的部分的点的答案,然后切成两半分别分治下去即可。

    总共分治n次

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define MN 150
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    vector<int> v[MN*MN+5];
    bool in[MN+5];
    int n,m,head[MN+5],cnt=1,tot=0,d[MN+5],q[MN+5],top,c[MN+5],Ans[MN+5][MN+5],bel[MN+5],S,T;
    struct edge{int to,next,w,tot;}e[30005];
    inline void ins(int f,int t,int w)
    {
        e[++cnt]=(edge){t,head[f],w,w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0,0};head[t]=cnt;
    }
    
    void rebuild(){for(int i=2;i<=cnt;++i)e[i].w=e[i].tot;}
    
    void Dfs(int x)
    {
        v[bel[x]=tot].push_back(x);
        for(int i=head[x];i;i=e[i].next)
            if(!bel[e[i].to]) Dfs(e[i].to);
    }
    
    int dfs(int x,int f)
    {
        if(x==T) return f;
        int used=0;
        for(int&i=c[x];i;i=e[i].next)
            if(e[i].w&&d[e[i].to]==d[x]+1)
            {
                int w=dfs(e[i].to,min(f-used,e[i].w));
                used+=w;e[i].w-=w;e[i^1].w+=w;
                if(used==f) return used;
            }
        return d[x]=-1,used;
    }
    
    bool bfs()
    {
        memset(d,0,sizeof(d));int i,j;
        for(d[q[top=i=1]=S]=1;i<=top;++i)
            for(j=c[q[i]]=head[q[i]];j;j=e[j].next)
                if(e[j].w&&!d[e[j].to]) d[q[++top]=e[j].to]=d[q[i]]+1;
        return d[T];
    }
    
    void Get(int x)
    {
        in[x]=1;
        for(int i=head[x];i;i=e[i].next)
            if(!in[e[i].to]&&e[i].w) Get(e[i].to);
    }
    
    void Solve(int now)
    {
        if(v[now].size()<2) {v[now].clear();return;}
        S=v[now][0],T=v[now][1];rebuild();int ans=0;
        while(bfs()) ans+=dfs(S,INF);
        memset(in,0,sizeof(in));Get(S);
        for(int i=1;i<=n;++i)
            for(int j=i+1;j<=n;++j)
                if(in[i]^in[j]) Ans[i][j]=min(Ans[i][j],ans);
        for(int i=1;i<=n;++i)
            if(bel[i]==now)
                bel[i]=(in[i]?tot+1:tot+2),v[bel[i]].push_back(i);
        int pre=tot;tot+=2;Solve(pre+1);Solve(pre+2);
        v[now].clear();
    }
    
    int main()
    {
        for(int cas=read();cas;--cas)
        {
            n=read();m=read();cnt=1;tot=0;
            memset(head,0,sizeof(head));
            memset(bel,0,sizeof(bel));
            memset(Ans,127,sizeof(Ans));
            for(int i=1;i<=m;++i)
            {
                int x=read(),y=read(),w=read();
                ins(x,y,w);ins(y,x,w);
            }
            for(int i=1;i<=n;++i)
                if(!bel[i]) ++tot,Dfs(i),Solve(tot);
            for(int i=1;i<=n;++i)
                for(int j=i+1;j<=n;++j)
                    Ans[i][j]>INF?Ans[i][j]=0:0;
            for(int q=read();q;--q)
            {
                int num=read(),ans=0;
                for(int i=1;i<n;++i)
                    for(int j=i+1;j<=n;++j)
                        if(Ans[i][j]<=num) ++ans;
                printf("%d
    ",ans);    
            }
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    [c++]基类对象作为函数參数(赋值兼容规则)
    easyui datagird 总计栏
    openssl之BIO系列之25---结束语
    具体解释Hibernate中的二级缓存
    记真实自己,炫精彩人生---《爱记》app使用体验
    设置-安全-手机加密功能解说
    Linux下Redis安装
    解题报告 之 HDU5317 RGCDQ
    FireFox所支持的全部标签(持续更新ing)
    本书已出版&lt;拨云见日:基于android的内核与系统架构源代码分析 &gt;
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2229.html
Copyright © 2011-2022 走看看