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

BZOJ 2561 最小生成树(最大流)

时间:2014-06-23 00:36:38      阅读:471      评论:0      收藏:0      [点我收藏+]

标签:style   class   blog   http   tar   ext   

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2561

题意:给定一个边带正权的连通无向图G= (V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树 上?

思路:考虑克鲁斯卡尔算法的过程。若加入的 边(u,v,L)能够出现在最小生成树中,那么权值小于L的边一定不能使得u和v连到一个连通分量中。因此问题等价于在权值小于L的边中选出最少的边使得 u和v不连通。那么我们将权值小于L的边建图,求最小割即可。最大生成树类似。

 

struct node
{
    int v,cap,next;
};


node edges[N<<2];
int head[N],e;


void add(int u,int v,int cap)
{
    edges[e].v=v;
    edges[e].cap=cap;
    edges[e].next=head[u];
    head[u]=e++;
}


void Add(int u,int v,int cap)
{
    add(u,v,cap);
    add(v,u,0);
}


int pre[N],cur[N],num[N],h[N];


int Maxflow(int s,int t,int n)
{
    int i;
    for(i=0;i<=n;i++) cur[i]=head[i],num[i]=h[i]=0;
    int u=s,Min,k,v;
    int ans=0;
    while(h[u]<n)
    {
        if(u==t)
        {
            Min=INF+1;
            for(i=s;i!=t;i=edges[cur[i]].v)
            {
                k=cur[i];
                if(edges[k].cap<Min) Min=edges[k].cap,v=i;
            }
            ans+=Min; u=v;
            for(i=s;i!=t;i=edges[cur[i]].v)
            {
                k=cur[i];
                edges[k].cap-=Min;
                edges[k^1].cap+=Min;
            }
        }
        for(i=cur[u];i!=-1;i=edges[i].next)
        {
            if(edges[i].cap>0&&h[u]==h[edges[i].v]+1) break;
        }
        if(i!=-1)
        {
            cur[u]=i;
            pre[edges[i].v]=u;
            u=edges[i].v;
        }
        else
        {
            if(--num[h[u]]==0) break;
            k=n;
            cur[u]=head[u];
            for(i=head[u];i!=-1;i=edges[i].next)
            {
                if(edges[i].cap>0&&h[edges[i].v]<k)
                {
                    k=h[edges[i].v];
                }
            }
            num[k+1]++;
            h[u]=k+1;
            if(u!=s) u=pre[u];
        }
    }
    return ans;
}


int a[N],b[N],W[N];
int n,m;


int main()
{
    RD(n,m);
    int i;
    FOR1(i,m) RD(a[i],b[i],W[i]);
    int u,v,w;
    RD(u,v,w);
    FOR1(i,n) head[i]=-1;
    e=0;
    FOR1(i,m) if(W[i]<w)
    {
        if(b[i]!=u&&a[i]!=v) Add(a[i],b[i],1);
        if(a[i]!=u&&b[i]!=v) Add(b[i],a[i],1);
    }
    int ans=Maxflow(u,v,n+1);
    FOR1(i,n) head[i]=-1; 
    e=0;
    FOR1(i,m) if(W[i]>w)
    {
        if(b[i]!=u&&a[i]!=v) Add(a[i],b[i],1);
        if(a[i]!=u&&b[i]!=v) Add(b[i],a[i],1);
    }
    ans+=Maxflow(u,v,n+1);
    PR(ans);
}

 

 

 

BZOJ 2561 最小生成树(最大流),布布扣,bubuko.com

BZOJ 2561 最小生成树(最大流)

标签:style   class   blog   http   tar   ext   

原文地址:http://www.cnblogs.com/jianglangcaijin/p/3799784.html

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