zoukankan      html  css  js  c++  java
  • SGU 176 【带上下界的有源汇的最小流】

    ---恢复内容开始---

    题意:

    给了n个点,m条有向边。

    接下来m行,每条边给起点终点与容量,以及一个标记。

    标记为1则该边必须满容量,0表示可以在容量范围内任意流。

    求:

    从源点1号点到终点n号点的最小的可行流。

    思路:

    ======================================================ge

    1.二分最小可行流【是复杂度偏高的一种】

    《一种简易的方法求解流量有上下界的网络中的网络流问题》

    我自己的东西只有在二分的时候。判断当前枚举的值是偏大还是偏小其实是1号点与附加源点或者附加汇点的边的容量来看的。

    坑点:

    SGU的PE都是骗人的,很多WA的情况会显示成PE。大家不要被骗==

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<string.h>
    #include<vector>
    #define MAXN 4050
    #define MAXM 40050
    using namespace std;
    const int inf=0x3f3f3f3f;
    vector<pair<pair<int,int>,pair<int,int> > >jilu;
    int inme[105],outme[105],n;
    struct Edge
    {
        int v,c,f,nx;
        Edge() {}
        Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
    } E[MAXM];
    int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],sz;
    void init()
    {
        sz=0;
        memset(G,-1,sizeof(G));
    }
    void add_edge(int u,int v,int c)
    {
        E[sz]=Edge(v,c,0,G[u]);
        G[u]=sz++;
        E[sz]=Edge(u,0,0,G[v]);
        G[v]=sz++;
    }
    bool bfs(int S,int T)
    {
        static int Q[MAXN];
        memset(dis,-1,sizeof(dis));
        dis[S]=0;
        Q[0]=S;
        for (int h=0,t=1,u,v,it; h<t; ++h)
        {
            for (u=Q[h],it=G[u]; ~it; it=E[it].nx)
            {
                if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
                {
                    dis[v]=dis[u]+1;
                    Q[t++]=v;
                }
            }
        }
        return dis[T]!=-1;
    }
    int dfs(int u,int T,int low)
    {
        if (u==T) return low;
        int ret=0,tmp,v;
        for (int &it=cur[u]; ~it&&ret<low; it=E[it].nx)
        {
            if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
            {
                if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
                {
                    ret+=tmp;
                    E[it].f+=tmp;
                    E[it^1].f-=tmp;
                }
            }
        }
        if (!ret) dis[u]=-1;
        return ret;
    }
    int dinic(int S,int T)
    {
        int maxflow=0,tmp;
        while (bfs(S,T))
        {
            memcpy(cur,G,sizeof(G));
            while (tmp=dfs(S,T,inf)) maxflow+=tmp;
        }
        return maxflow;
    }
    int check(){
        bool ok=1;
        memcpy(cur,G,sizeof(G));
        for(int i=1;i<=n;i++){
            if(ok==0)break;
            if(inme[i]-outme[i]>=0){
                for (int it=cur[0]; ~it; it=E[it].nx){
                    int v=E[it].v;
                    if(v==i){
                        if(E[it].f!=E[it].c){
                            ok=0;
                        }
                        break;
                    }
                }
            }
            else{
                for(int it=cur[i];~it;it=E[it].nx){
                    int v=E[it].v;
                    if(v==n+1){
                        if(E[it].f!=E[it].c){
                            ok=0;
                        }
                        break;
                    }
                }
            }
        }
        if(ok)return 0;
        if(inme[1]>=outme[1])
            for(int it=cur[0];~it;it=E[it].nx){
                int v=E[it].v;
                if(v==1){
                    if(E[it].f==E[it].c){
                        return -1;
                    }
                    else{
                        return 1;
                    }
                }
            }
        else
            for(int it=cur[1];~it;it=E[it].nx){
                int v=E[it].v;
                if(v==n+1){
                    if(E[it].f==E[it].c){
                        return 1;
                    }
                    else{
                        return -1;
                    }
                }
            }
    }
    int main()
    {
        int m,sum1=0,sum2=0;
        scanf("%d%d",&n,&m);
        int a,b,c,d;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&a,&b,&c,&d);
            if(a==1)sum1+=c;
            if(b==n)sum2+=c;
            if(d)d=c;
            inme[b]+=d;
            outme[a]+=d;
            jilu.push_back(make_pair(make_pair(a,b),make_pair(c,d)));
        }
        int l=0,r=10000010;
        while(l<=r){
            init();
            int mid=(l+r)>>1;
            inme[1]+=mid;
            outme[n]+=mid;
            for(int i=0;i<m;i++){
                a=jilu[i].first.first;
                b=jilu[i].first.second;
                c=jilu[i].second.first;
                d=jilu[i].second.second;
                add_edge(a,b,c-d);
            }
            for(int i=1;i<=n;i++){
                if(inme[i]>=outme[i]){
                    add_edge(0,i,inme[i]-outme[i]);
                }
                else{
                    add_edge(i,n+1,outme[i]-inme[i]);
                }
            }
            dinic(0,n+1);
            if(check()>=0)r=mid-1;
            else l=mid+1;
            inme[1]-=mid;
            outme[n]-=mid;
        }
        init();
        inme[1]+=l;
        outme[n]+=l;
        for(int i=0;i<m;i++){
            a=jilu[i].first.first;
            b=jilu[i].first.second;
            c=jilu[i].second.first;
            d=jilu[i].second.second;
            add_edge(a,b,c-d);
        }
        for(int i=1;i<=n;i++){
            if(inme[i]>=outme[i]){
                add_edge(0,i,inme[i]-outme[i]);
            }
            else{
                add_edge(i,n+1,outme[i]-inme[i]);
            }
        }
        dinic(0,n+1);
        if(check()==0){
            printf("%d
    ",l);
            memcpy(cur,G,sizeof(G));
            for(int i=0;i<m;i++){
                int u=jilu[i].first.first;
                int v=jilu[i].first.second;
                int c=jilu[i].second.second;
                for(int it=cur[u];~it;it=E[it].nx){
                    if(E[it].v==v){
                        printf("%d",E[it].f+c);
                        if(i!=m-1)printf(" ");
                        break;
                    }
                }
            }
            printf("
    ");
        }
        else{
            puts("Impossible");
        }
        return 0;
    }

    ---恢复内容结束---

  • 相关阅读:
    《构建之法》第8、9、10章 读后感
    [团队项目]SCRUM项目6.0 7.0 (新)
    [团队项目]SCRUM项目5.0
    [团队项目]SCRUM项目4.0
    [团队项目] Scrum 项目 3.0 SCRUM 流程的步骤2: Spring 计划
    [操作系统]实验三 进程调度模拟程序
    [团队项目] Scrum 项目 2.0 产品BACKLOG
    复利计算的总结
    复利/单利计算程序进度0321更新
    0312 复利计算器2.0 运行与介绍
  • 原文地址:https://www.cnblogs.com/tun117/p/5392424.html
Copyright © 2011-2022 走看看