zoukankan      html  css  js  c++  java
  • HDU3157:Crazy Circuits——题解

    http://acm.hdu.edu.cn/showproblem.php?pid=3157

    题目大意:给一个电路 ,起点为+,终点为-,包括起点终点在内的电元件之间有有下界边,求最小流。

    ————————————————————————————————

    上下界网络流完结之题,显然是要求最小流的。

    (然而自从做了上下界网络流之后我发现网上的题解是真的坑……有的人样例都不过就敢把代码粘到网上,有的人最小流做法是错的……)

    这里仍然推荐这个人的博客,至少是对的:https://www.cnblogs.com/kane0526/archive/2013/04/05/3001108.html

    首先先和上下界最大流是一样的操作,只是我们先不建ed到st的inf的边,我们先跑一遍,等跑不动了之后再建再跑。

    这样做显然可以先将环先跑完,然后再跑别的,有效减少ed到st的流量,进而减少最小流。

    因此我们的最小流就是ed到st的inf的边的反边的流量。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=105;
    const int M=1005;
    const int INF=2147483647;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        int nxt,to,w;
    }edge[M];
    int head[N],du[N];
    int cnt=-1,S,T,st,ed;
    inline void add(int u,int v,int w){
        cnt++;
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].nxt=head[u];
        head[u]=cnt;
        return;
    }
    int lev[N],cur[N],dui[N];
    bool bfs(int k){
        int r=0;
        for(int i=1;i<=k;i++){
        lev[i]=-1;
        cur[i]=head[i];
        }
        dui[0]=S,lev[S]=0;
        int u,v;
        for(int l=0;l<=r;l++){
        u=dui[l];
        for(int e=head[u];e!=-1;e=edge[e].nxt){
            v=edge[e].to;
            if(edge[e].w>0&&lev[v]==-1){
            lev[v]=lev[u]+1;
            r++;
            dui[r]=v;
            if(v==T)return 1;
            }
        }
        }
        return 0;
    }
    int dinic(int u,int flow,int k){
        if(u==k)return flow;
        int res=0,delta;
        for(int &e=cur[u];e!=-1;e=edge[e].nxt){
        int v=edge[e].to;
        if(edge[e].w>0&&lev[u]<lev[v]){ 
            delta=dinic(v,min(edge[e].w,flow-res),k); 
            if(delta>0){
            edge[e].w-=delta;
            edge[e^1].w+=delta;
            res+=delta;
            if(res==flow)break; 
            }
        }
        }
        if(res!=flow)lev[u]=-1;
        return res;
    }
    inline void init(){
        memset(head,-1,sizeof(head));
        memset(du,0,sizeof(du));
        cnt=-1;
        return;
    }
    inline int getc(){
        char ch=getchar();
        while(ch==' '||ch=='
    ')ch=getchar();
        if(ch=='+')return st;
        if(ch=='-')return ed;
        int X=0;
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return X;
    }
    int main(){
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF){
        if(n+m==0)break;
        init();
        st=n+1,ed=st+1;
        for(int i=1;i<=m;i++){
            int u=getc(),v=getc(),c=read();
            add(u,v,INF-c);add(v,u,0);
            du[u]-=c;du[v]+=c;
        }
        int full=0,ans=0;
        S=ed+1;T=S+1;
        for(int i=1;i<=ed;i++){
            if(du[i]>0){
            add(S,i,du[i]);add(i,S,0);
            full+=du[i];
            }else if(du[i]<0){
            add(i,T,-du[i]);add(T,i,0);
            }
        }
        while(bfs(T))ans+=dinic(S,INF,T);
        add(ed,st,INF);add(st,ed,0);
        while(bfs(T))ans+=dinic(S,INF,T);
        if(ans!=full)puts("impossible");
        else{
            printf("%d
    ",edge[cnt].w);
        }
        }
        return 0;
    }
  • 相关阅读:
    牛牛与LCM(最小公约数)
    小明的挖矿之旅_牛客网(思维题)
    2019/4/20周赛 F题 CodeForces
    哥德巴赫猜想_2019/7/11_牛客网
    智障操作-wireless AC 9462
    codeforces762A
    2019中山大学程序设计竞赛(重现赛)斐波那契/
    Java自学笔记(10):【面向对象 】 类和对象、构造方法、this关键字
    Java自学笔记(9):方法
    Java自学笔记(8):多维数组
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8227978.html
Copyright © 2011-2022 走看看