• BZOJ 2561 最小生成树


    第一眼瞎那啥贪心,然后觉得不太对劲,就滚去看题解,发现是网络流OTZ

    模拟Kruskal的过程发现,若<u,v>要在最小生成树中出现,权值则小于<u,v>的边不能让u,v联通,转换成最小割模型,最大生成树同理。

    跑两遍最大流。

    注意边要建双向的啊,被这点坑死了。然后板子不要瞎那啥乱打。

    顺便发现果然ISAP跑得很快。

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define INF 0x3f3f3f3f
    typedef long long LL;
    using namespace std;
    
    const int maxn=1e6+299;
    
    int ecnt=1,ans,n,m,u,v,w,fir[maxn],pre[maxn];
    
    struct Edge {
        int u,v,w,no,vv;
        Edge(){}
        Edge(int u,int v,int w):u(u),v(v),w(w){}
    }ee[maxn];
    
    struct edge {
        int from,to,flow,cap,nxt;
        edge(){}
        edge(int from,int to,int cap,int flow,int nxt):from(from),to(to),cap(cap),flow(flow),nxt(nxt){}
    }e[maxn];
    
    int d[maxn],c[maxn],cur[maxn];
    
    void add(int from,int to,int cap) {
        e[++ecnt]=edge(from,to,cap,0,fir[from]); fir[from]=ecnt;
        e[++ecnt]=edge(to,from,0,0,fir[to]); fir[to]=ecnt;
    }
    queue<int>que;
    void bfs(int s,int t) {
        for(int i=1;i<=n;i++) d[i]=n;
        d[t]=0;
        que.push(t); 
        while(!que.empty()) {
            int x=que.front(); que.pop();
            for(int i=fir[x];i;i=e[i].nxt) {
                edge tp=e[i];
                if(d[e[i].to]==n&&e[i].flow==e[i].cap) {
                    int to=e[i].to;
                    d[to]=d[x]+1;
                    que.push(to);     
                }
            }
        }
    }
    
    int cal(int s,int t) {
        int fl=1e9;
        for(int i=t;i!=s;i=e[pre[i]].from) 
            fl=min(fl,e[pre[i]].cap-e[pre[i]].flow);
        for(int i=t;i!=s;i=e[pre[i]].from) {
            e[pre[i]].flow+=fl;
            e[pre[i]^1].flow-=fl;
        }
        return fl;
    } 
    int maxflow(int s,int t) {
        int res=0;
        bfs(s,t);
        for(int i=1;i<=n;i++) cur[i]=fir[i],c[d[i]]++;
        for(int x=s;d[x]<n;) {
            if(x==t) {
                res+=cal(s,t);
                x=s;
            }
            int ok=0;
            for(int &i=cur[x];i;i=e[i].nxt) 
                if(d[e[i].to]+1==d[x]&&e[i].cap>e[i].flow) {
                    pre[x=e[i].to]=i;
                    ok=1; break;
                }
            if(!ok) {
                cur[x]=fir[x]; int M=n;
                for(int i=fir[x];i;i=e[i].nxt) {
                    if(e[i].cap>e[i].flow&&(M>d[e[i].to]+1)) M=d[e[i].to]+1;
                }
                if(!(--c[d[x]])) break;
                c[d[x]=M]++;
                if(x!=s) x=e[pre[x]].from;
            }
        }
        return res;
    }
    int main()
    {
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++) {
            scanf("%d%d%d",&u,&v,&w);
            ee[i]=Edge(u,v,w);
        }
        scanf("%d%d%d",&u,&v,&w);
        for(int i=1;i<=m;i++)     {
            if(ee[i].w<w) {
                add(ee[i].u,ee[i].v,1);
                add(ee[i].v,ee[i].u,1);
           }
        }
        ans+=maxflow(u,v);
        memset(fir,0,sizeof(fir));
        memset(pre,0,sizeof(pre));
        ecnt=1;
        for(int i=1;i<=m;i++) {
            if(ee[i].w>w) {
                add(ee[i].u,ee[i].v,1);
                add(ee[i].v,ee[i].u,1);
            }
        }
        ans+=maxflow(u,v);
        printf("%d
    ",ans);
        return 0;
    }
    View Code

     

  • 相关阅读:
    matlab图像对比度增强,拉伸和灰度变换
    javascript 数据结构----集合
    reduce ,redceRight 在react中的使用
    找前端私活
    数组对象 按某个属性排序
    原生js获取scrollTop
    react 绑定事件 总是默认触发
    横向柱状图
    css 四角辉光
    Android学习笔记_点九绘图与软键盘和事件传递
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7604812.html
Copyright © 2020-2023  润新知