zoukankan      html  css  js  c++  java
  • BZOJ2561 最小生成树(最小割)

      考虑kruskal的过程:按边权从小到大考虑,如果这条边的两端点当前不连通则将其加入最小生成树。由此可以发现,某条边可以在最小生成树上的充要条件是其两端点无法通过边权均小于它的边连接。

      那么现在我们需要删一些边使两点不连通,显然是最小割。对最小和最大分别做一次即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 20010
    #define M 200010
    int S,T,v,n,m,p[N],cur[N],q[N],d[N],t,ans=0;
    struct data{int to,nxt,cap,flow;
    }edge[M<<2];
    struct data1
    {
        int x,y,z;
        bool operator <(const data1&a) const
        {
            return z<a.z;
        }
    }e[M];
    void addedge(int x,int y)
    {
        t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=1,edge[t].flow=0,p[x]=t;
        t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,edge[t].flow=0,p[y]=t;
    }
    bool bfs()
    {
        memset(d,255,sizeof(d));d[S]=0;
        int head=0,tail=1;q[1]=S;
        do
        {
            int x=q[++head];
            for (int i=p[x];~i;i=edge[i].nxt)
            if (d[edge[i].to]==-1&&edge[i].flow<edge[i].cap)
            {
                d[edge[i].to]=d[x]+1;
                q[++tail]=edge[i].to;
            }
        }while (head<tail);
        return ~d[T];
    }
    int work(int k,int f)
    {
        if (k==T) return f;
        int used=0;
        for (int i=cur[k];~i;i=edge[i].nxt)
        if (d[k]+1==d[edge[i].to])
        {
            int w=work(edge[i].to,min(f-used,edge[i].cap-edge[i].flow));
            edge[i].flow+=w,edge[i^1].flow-=w;
            if (edge[i].flow<edge[i].cap) cur[k]=i;
            used+=w;if (used==f) return f;
        }
        if (used==0) d[k]=-1;
        return used;
    }
    void dinic()
    {
        while (bfs())
        {
            memcpy(cur,p,sizeof(p));
            ans+=work(S,M);
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2561.in","r",stdin);
        freopen("bzoj2561.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=m;i++) e[i].x=read(),e[i].y=read(),e[i].z=read();
        sort(e+1,e+m+1);
        S=read(),T=read(),v=read();
        memset(p,255,sizeof(p));t=-1;
        for (int i=1;i<=m;i++)
        if (e[i].z<v) addedge(e[i].x,e[i].y),addedge(e[i].y,e[i].x);
        else break;
        dinic();
        memset(p,255,sizeof(p));t=-1;
        for (int i=m;i>=1;i--)
        if (e[i].z>v) addedge(e[i].x,e[i].y),addedge(e[i].y,e[i].x);
        else break;
        dinic();
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    poj 1328 Radar Installation (贪心)
    hdu 2037 今年暑假不AC (贪心)
    poj 2965 The Pilots Brothers' refrigerator (dfs)
    poj 1753 Flip Game (dfs)
    hdu 2838 Cow Sorting (树状数组)
    hdu 1058 Humble Numbers (DP)
    hdu 1069 Monkey and Banana (DP)
    hdu 1087 Super Jumping! Jumping! Jumping! (DP)
    必须知道的.NET FrameWork
    使用记事本+CSC编译程序
  • 原文地址:https://www.cnblogs.com/Gloid/p/9582174.html
Copyright © 2011-2022 走看看