World final 2012 (Chips Challenge-无源汇最小费用流)
来源:互联网 发布:萧航网络 编辑:程序博客网 时间:2024/06/13 13:08
每块芯片都被设计成N*N(
你需要满足限制如下:
1. 部分插槽不可用
2. 部分插槽已经被组件占据
3. 第i行和第i列组件数目必须相同
4. 对于给出的
问最多能再放几个组件。
枚举答案,对于每个答案建立二分图,为了保证条件(3),将右边节点向左边节点连边,如果有解,则
- totcost/inf=C的个数
- totcost%inf=放组件的个数
建图,根据doc老师建的四分图再改成二分图后,
我们得到了这样的无缘无汇最小费用循环流。
无缘无汇最小费用循环流求解:查询图中有无负环,有则满流,无则继续在残余网络上找,直至无负环为止。
spfa时先把所有点压进队列,并假设
由于每次负环最优查询为
#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
- World final 2012 (Chips Challenge-无源汇最小费用流)
- UVALive 5131 Chips Challenge 费用流
- 每个顶点指定流量的无源汇最小费用流(80人环游地球)
- bzoj 3876: [Ahoi2014]支线剧情 (无源汇最小费用可行流)[省选计划系列]
- [无源汇上下界最小费用可行流 差分费用流] BZOJ 1061 [Noi2008]志愿者招募
- bzoj 1927: [Sdoi2010]星际竞速 (无源汇有上下界最小费用可行流) [省选计划系列]
- [无源汇最大费用可行流 差分费用流] Codeforces 717G Bubble Cup 9 - Finals G. Underfail
- jzoj 100003. 【NOI2017模拟.4.1】 Tree 无源汇最大费用流
- 最小费用最小流uva10746
- 最小费用最大流
- 最小费用最大流
- 最小费用最大流
- 最小费用最大流
- 最小费用流模版
- 【最小费用最大流】
- 最小费用流
- 最小费用最大流
- 最小费用最大流
- 【.net 深呼吸】自己动手来写应用程序设置类
- PHP中的HTTP认证
- IDEA 'Generics are not supported at this language level'报错解决
- 2017 Multi-University Training Contest
- Linux 基本常用命令 用户 useradd,userdel,su,passwd
- World final 2012 (Chips Challenge-无源汇最小费用流)
- 通过API文档查询Math类的方法,打印出近似圆,只要给定不同半径,圆的大小随之发生改变
- 日常问题总结(1)
- 你真的了解UIView吗?
- 在Lua中使用自定义类——tolua++工具使用
- 矩阵乘法优化--poj3318 随机矩阵
- onvif soap接口代码框架的关联
- spark之4:编程指南
- 第三节总结