World final 2012 (Chips Challenge-无源汇最小费用流)

来源:互联网 发布:萧航网络 编辑:程序博客网 时间:2024/06/13 13:08

每块芯片都被设计成N*N(N<=40)的带插槽的正方形。
你需要满足限制如下:
1. 部分插槽不可用
2. 部分插槽已经被组件占据
3. 第i行和第i列组件数目必须相同
4. 对于给出的A,B,任何行和列的组件总数不超过芯片上组数的A/B
问最多能再放几个组件。

枚举答案,对于每个答案建立二分图,为了保证条件(3),将右边节点向左边节点连边,如果有解,则
- totcost/inf=C的个数
- totcost%inf=放组件的个数

建图,根据doc老师建的四分图再改成二分图后,
我们得到了这样的无缘无汇最小费用循环流。

Chips Challenge

无缘无汇最小费用循环流求解:查询图中有无负环,有则满流,无则继续在残余网络上找,直至无负环为止。
spfa时先把所有点压进队列,并假设di=0,执行SPFA观察是否有点进队超过n2次,这样期望找出负环的时间复杂度大致为O(n2logn)(我也不确定)。
由于每次负环最优查询为O(n2),大概可以证明这个程序复杂度O(n5)

#include<bits/stdc++.h> using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define ForkD(i,k,n) for(int i=n;i>=k;i--)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define RepD(i,n) for(int i=n;i>=0;i--)#define Forp(x) for(int p=Pre[x];p;p=Next[p])#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  #define Lson (o<<1)#define Rson ((o<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define MEMI(a) memset(a,0x3f,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define MEMx(a,b) memset(a,b,sizeof(a));#define INF (0x3f3f3f3f)#define F (1000000007)#define pb push_back#define mp make_pair#define fi first#define se second#define vi vector<int> #define pi pair<int,int>#define SI(a) ((a).size())#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;#define PRi2D(a,n,m) For(i,n) { \                        For(j,m-1) cout<<a[i][j]<<' ';\                        cout<<a[i][m]<<endl; \                        } #pragma comment(linker, "/STACK:102400000,102400000")#define ALL(x) (x).begin(),(x).end()#define gmax(a,b) a=max(a,b);#define gmin(a,b) a=min(a,b);typedef long long ll;typedef long double ld;typedef unsigned long long ull;ll mul(ll a,ll b){return (a*b)%F;}ll add(ll a,ll b){return (a+b)%F;}ll sub(ll a,ll b){return ((a-b)%F+F)%F;}void upd(ll &a,ll b){a=(a%F+b%F)%F;}inline int read(){    int x=0,f=1; char ch=getchar();    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}    return x*f;} int n,a,b; char s[50][50];int col[50],row[50];#define MAXN (210)#define MAXM ((40+40+40*40+40)*2+100)class Cost_Flow  {  public:      int n,s,t;      int edge[MAXM],Next[MAXM],Pre[MAXN],weight[MAXM],size;      int cost[MAXM];      void addedge(int u,int v,int w,int c)        {            edge[++size]=v;            weight[size]=w;            cost[size]=c;            Next[size]=Pre[u];            Pre[u]=size;        }        void addedge2(int u,int v,int w,int c=0){addedge(u,v,w,c),addedge(v,u,0,-c);}       bool b[MAXN];      int d[MAXN],inq[MAXN];      int pr[MAXN],ed[MAXN];     queue<int> q;    int Find_Negative_Circle()        {            while(!q.empty()) q.pop();         For(i,n) d[i]=inq[i]=0;        For(i,n) q.push(i),inq[i]=1;        int nowv=0;        while(!q.empty()) {            int now=q.front();q.pop();            Forp(now) {                int v=edge[p];                if(weight[p]&&d[now]+cost[p]<d[v]) {                    d[v]=d[now]+cost[p];                    inq[v]++;                    if (inq[v]>n) {                        nowv=v;                        break;                    }                    q.push(v);                        pr[v]=now,ed[v]=p;                    }            }            if (nowv) break;        }        if (!nowv) return 0;        MEM(b)        for(nowv;!b[nowv];nowv=pr[nowv]) {            b[nowv]=1;nowv=pr[nowv];         }         return nowv;    }    int totcost;        int CostFlow()        {        int nowv=0,maxflow=0;        while (nowv=Find_Negative_Circle())            {                int flow=INF,c=0,x=nowv;                do  {                c+=cost[ed[x]];                flow=min(flow,weight[ed[x]]);                x=pr[x];            } while(x!=nowv);            if (!c) break;            totcost+=flow*c;             maxflow+=flow;               x=nowv;            do  {                weight[ed[x]]-=flow,weight[ed[x]^1]+=flow;                x=pr[x];            }while(x!=nowv);        }            return totcost;        }        void mem(int n,int s,int t)      {          (*this).n=n;  (*this).s=s;(*this).t=t;        size=1;          totcost=0;          MEM(Pre) MEM(Next)       }  }S;  int idr[MAXN],idc[MAXN];int main(){//  freopen("A.in","r",stdin);//  freopen(".out","w",stdout);    int kcase=1;    while(scanf("%d%d%d",&n,&a,&b)==3 && n) {        MEM(col) MEM(row)        int L=0,R=n*n;        For(i,n) {            scanf("%s",s[i]+1);            For(j,n) {                if (s[i][j]=='C') row[i]++,col[j]++,L++;                if (s[i][j]=='/') --R;                if (s[i][j]=='.') row[i]++,col[j]++;            }        }        int ans=-1;        R=min(R,n*n*a/b);        Fork(f,L,R){            int maxl=f*a/b;            if (f>L) {                if (maxl!=(f-1)*a/b) {                    For(i,n) {                        int l1=min(maxl,min(col[i],row[i]))-min((f-1)*a/b,min(col[i],row[i]));                        S.weight[idr[i]]+=l1;                    }                   }            } else {                S.mem(2*n,2*n,2*n);                For(i,n) {                    S.addedge2(n+i,i,min(maxl,min(col[i],row[i])));                    idr[i]=S.size-1;                }                For(i,n) For(j,n) {                    if (::s[i][j]=='C') {                        S.addedge2(i,n+j,1,-1e6);                    } else if (::s[i][j]=='.'){                        S.addedge2(i,n+j,1,-1);                    }                }            }             int p=S.CostFlow();             if (p==L-f-L*1e6) {                ans=max(ans,f-L);            }        }        printf("Case %d: ",kcase++);        if (ans^-1) printf("%d\n",ans);        else puts("impossible");    }    return 0;}
阅读全文
0 0
原创粉丝点击