zoukankan      html  css  js  c++  java
  • 题解 [SHOI2010]最小生成树

     题面

    解析

    看上去是黑题啊!

    实际上也就是道网络流最大流。

    当然,我们也知道网络流最关键的是建图。

    首先,分析一下题目:

    题目要求在操作后使给定的边lab一定在最小生成树上,

    求最小的操作数。

    先设lab连通的边为A,B。

    那么,根据Krustal算法,在加入lab时一定没有权值比lab小的边使A,B连通。

    所以,只要将权值比lab小的边重新建图,

    将容量设为这条边最少的操作次数就行了。

    而最小的操作次数就应该是wlab −wi +1。

    最后求A到B的最小割(最大流)就行了。

    上AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read(){
        int sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
        return f*sum;
    }
    
    
    const int INF=0x3f3f3f3f;
    struct road{
        int next,to,w;
    }e[100001];
    struct line{
        int x,y,w;
    }a[100001];
    int n,m,lab;
    int s,t;
    int head[10001],cnt=1;
    int d[100001],v[100001];
    
    void add(int x,int y,int w){
        e[++cnt].to=head[x];
        e[cnt].next=y;
        e[cnt].w=w;
        head[x]=cnt;
    }
    
    bool bfs(){
        memset(d,-1,sizeof(d));
        memset(v,0,sizeof(v));
        queue <int> que;
        que.push(s);
        v[s]=1;
        d[s]=1;
        while(!que.empty()){
            int x=que.front();
            que.pop();
            for(int i=head[x];i;i=e[i].to){
                int k=e[i].next;
                if(v[k]||!e[i].w) continue;
                v[k]=1;
                d[k]=d[x]+1;            
                que.push(k);
            }
        }
        if(d[t]>0) return 1;
        return 0;
    }
    
    int dfs(int x,int low){
        if(x==t) return low;
        int c=0;
        for(int i=head[x];i;i=e[i].to){
            int k=e[i].next;
            if(d[k]!=d[x]+1) continue;
            if(!e[i].w) continue;
            if((c=dfs(k,min(low,e[i].w)))){
                e[i].w-=c;
                e[i^1].w+=c;
                return c;
            }
        }
        return 0;
    }
    
    void DINIC(){
        int ans=0,mi;
        while(bfs()){
            while((mi=dfs(s,INF))) ans+=mi;
        }
        printf("%d
    ",ans);
        return ;
    }
    
    int main(){
    //    freopen("mst.in","r",stdin);
    //    freopen("mst.out","w",stdout);
        n=read();m=read();lab=read();
        for(int i=1;i<=m;i++){
            a[i].x=read();a[i].y=read();a[i].w=read();
        }
        s=a[lab].x;t=a[lab].y;
        for(int i=1;i<=m;i++){
            if(a[i].w<=a[lab].w&&i!=lab){
                add(a[i].x,a[i].y,a[lab].w-a[i].w+1);
                add(a[i].y,a[i].x,0);
                add(a[i].y,a[i].x,a[lab].w-a[i].w+1);
                add(a[i].x,a[i].y,0);            
            }
        }
        DINIC();
        return 0;
    }
  • 相关阅读:
    STL中string的源码解读
    Sublime插件:Terminal
    sublime text3安装Package Control
    [转]Sublime Text操作
    python itertools模块实现排列组合
    pandas 选择某几列
    更改pandas dataframe 列的顺序
    pandas之groupby分组与pivot_table透视表
    IPython notebook快捷键(Jupyter notebook)
    人生的意义
  • 原文地址:https://www.cnblogs.com/zsq259/p/10502130.html
Copyright © 2011-2022 走看看