• 2020/10/23 模拟赛 chip


    Description

    一张$n imes n$的芯片上,有些格子己经焊有零件,有些格子禁止焊接零件。问,在同时满足下面 三个约束的前提下,至多可以再焊接多少个零件。

    1. 每个格子至多焊接一个零件
    2. 第$i$行的零件总数和第$i$列一致
    3. 任意一行的零件数不得超过总零件数的$frac AB$

    Solution

    带负环的费用流

    枚举总零件数的$frac AB$,建图跑费用流,设$hangnum$为第$i$行一开始就有的零件数

    1.  从第$i$行向第$i$列连边,容量为$lim-hangnum_i$,费用为$0$
    2.  若$hangnum > lienum$,从$S$连向第$i$列,容量为$delta$,费用为$0$
    3.  若$hangnum < lienum$,从第$i$行连向$T$,容量为$delta$,费用为$0$
    4.  若$(i,j)$可以放置,从第$j$列连向第$i$行,容量为$1$,费用为$0$

    最小费用最大流的相反数即为答案

    但是会出现负环,所以要先走一遍负环

    将原图中每个点拆成入点和出点,对应的每一条边在新图中由入点连向出点,可以保证所有负环不再组成负环,被拆分成多条独立的路径,原来的路径一定不在最大流中、

    在新图中跑最小费用最大流就可以计算所有负环的费用,再对应着将流量改回原图,在该残余网络上跑最小费用最大流就不会陷入死循环

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    using namespace std;
    int n,A,B,delta[45],hangcan[45],liecan[45],hangnum[45],lienum[45],total,ans=-1,cnt;
    const int INF=0x7f7f7f7f;
    char map[45][45];
    struct Edge
    {
        int head[355],nxt[50005],to[50005],w[50005],dis[50005],sta[50005],dist[355],tot,S,T;
        bool vst[355];
        void clear()
        {
            memset(head,0,sizeof(head));
            tot=1;
        }
        void addedge(int u,int v,int c,int d)
        {
            nxt[++tot]=head[u];
            head[u]=tot;
            to[tot]=v;
            sta[tot]=u;
            w[tot]=c;
            dis[tot]=d;
            nxt[++tot]=head[v];
            head[v]=tot;
            to[tot]=u;
            sta[tot]=v;
            w[tot]=0;
            dis[tot]=-d;
        }
        bool SPFA(int s,int t)
        {
            memset(dist,127,sizeof(dist));
            memset(vst,false,sizeof(vst));
            queue<int>q;
            vst[s]=true;
            dist[s]=0;
            q.push(s);
            while(q.size())
            {
                int u=q.front();
                q.pop();
                for(int i=head[u];i;i=nxt[i])
                {
                    int v=to[i];
                    if(w[i]>0&&dist[v]>dist[u]+dis[i])
                    {
                        dist[v]=dist[u]+dis[i];
                        if(!vst[v])
                        {
                            vst[v]=true;
                            q.push(v);
                        }
                    }
                }
                vst[u]=false;
            }
            return dist[t]<INF;
        }
        int DFS(int s,int flow,int t)
        {
            if(s==t||flow<=0)
            {
                return flow;
            }
            int rest=flow;
            vst[s]=true;
            for(int i=head[s];i;i=nxt[i])
            {
                int v=to[i];
                if(w[i]>0&&dist[s]+dis[i]==dist[v]&&!vst[v])
                {
                    int k=DFS(v,min(rest,w[i]),t);
                    rest-=k;
                    w[i]-=k;
                    w[i^1]+=k;
                    if(rest<=0)
                    {
                        break;
                    }
                }
            }
            return flow-rest;
        }
        void ZKW(int &costs)
        {
            while(SPFA(S,T))
            {
                memset(vst,false,sizeof(vst));
                costs+=dist[T]*DFS(S,INF,T);
            }
        }
        bool check()
        {
            for(int i=head[S];i;i=nxt[i])
            {
                if(!(i&1)&&w[i])
                {
                    return false;
                }
            }
            return true;
        }
    }G1,G2;
    inline int read()
    {
        int f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            w=(w<<1)+(w<<3)+ch-'0';
            ch=getchar();
        }
        return f*w;
    }
    int X(int a,int t)
    {
        return a*2+t+1;
    }
    int xiaoquan()
    {
        G2.T=320;
        for(int i=2;i<=G1.tot;i+=2)
        {
            G2.addedge(X(G1.sta[i],0),X(G1.to[i],1),G1.w[i],G1.dis[i]);
        }
        for(int i=0;i<=G1.T;i++)
        {
            if((i>n&&i<100)||(i>100+n&&i<G1.T))
            {
                continue;
            }
            G2.addedge(G2.S,X(i,0),INF,0);
            G2.addedge(X(i,1),G2.T,INF,0);
            G2.addedge(X(i,0),X(i,1),INF,0);
        }
        int costs=0;
        G2.ZKW(costs);
        for(int i=2;i<=G1.tot;i+=2)
        {
            int del=G1.w[i]-G2.w[i];
            G1.w[i]-=del;
            G1.w[i^1]+=del;
        }
        return -costs;
    }
    void calc(int lim)
    {
        G1.clear();
        G2.clear();
        for(int i=1;i<=n;i++)
        {
            if(lienum[i]>lim||hangnum[i]>lim)
            {
                return;
            }
        }
        G1.S=G2.S=0;
        G1.T=G2.T=153;
        for(int i=1;i<=n;i++)
        {
            G1.addedge(i,i+100,lim-hangnum[i],0);
            if(delta[i]>0)
            {
                G1.addedge(G1.S,i+100,delta[i],0);
            }
            else if(delta[i]<0)
            {
                G1.addedge(i+100,G1.T,-delta[i],0);
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(map[i][j]=='.')
                {
                    G1.addedge(j+100,i,1,-1);
                }
            }
        }
        int ttt=xiaoquan(),costs=0;
        G1.ZKW(costs);
        if(!G1.check())
        {
            return;
        }
        ttt-=costs;
        if((double)(ttt+cnt)*A/B>=lim)
        {
            ans=max(ans,ttt);
        }
    }
    int main()
    {
        n=read();
        A=read();
        B=read();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                map[i][j]=getchar();
                if(map[i][j]=='C')
                {
                    ++total;
                    ++cnt;
                    ++delta[i];
                    --delta[j];
                    ++hangnum[i];
                    ++lienum[j];
                    ++hangcan[i];
                    ++liecan[j];
                }
                else if(map[i][j]=='.')
                {
                    ++total;
                    ++hangcan[i];
                    ++liecan[j];
                }
            }
            getchar();
        }
        for(int i=1;i<=n;i++)
        {
            if(hangnum[i]>(double)total*A/B||min(hangcan[i],liecan[i])<max(hangnum[i],lienum[i]))
            {
                puts("impossible");
                return 0;
            }
        }
        for(int i=n;i>=1;i--)
        {
            calc(i);
            if(ans!=-1)
            {
                break;
            }
        }
        if(ans==-1)
        {
            for(int i=1;i<=n;i++)
            {
                if(delta[i]||hangnum[i]>(double)cnt*A/B)
                {
                    puts("impossible");
                    return 0;
                }
            }
            puts("0");
            return 0;
        }
        printf("%d
    ",ans);
        return 0;
    }
    chip
  • 相关阅读:
    Google哲学(一)
    Predictably Irractional 相对论的真相
    .NET使用OpenSSL生成的pem密钥文件【做电子商务的朋友可能需要】
    从开辟蓝海到保卫蓝海(一)
    礼让?
    登门槛策略
    从开辟蓝海到保卫蓝海(四)
    盛大招聘 高级数据库开发工程师 工作地点张江高科 学历高者,经验可放宽
    Show一下拿的奖杯
    我们家的一坨和田仔玉[三色皮]
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13933620.html
Copyright © 2020-2023  润新知