题解:
丢链跑点这里。
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=85;
const int inf=2147483647;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n,A,B,mp[42][42];
struct Edge{int x,y,d,c,next;}e[2000000];
int len=1,last[Maxn];
void ins(int x,int y,int d,int c)
{
int t=++len;
e[t].x=x;e[t].y=y;e[t].d=d;e[t].c=c;
e[t].next=last[x];last[x]=t;
}
void addedge(int x,int y,int d,int c){if(!d)return;ins(x,y,d,c);ins(y,x,0,-c);}
int st,ed;
int f[Maxn],pre[Maxn];
bool in[Maxn];
bool spfa()
{
queue<int>q;q.push(st);
pre[st]=-1;
memset(f,63,sizeof(f));f[st]=0;
memset(in,false,sizeof(in));
while(!q.empty())
{
int x=q.front();q.pop();in[x]=false;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(e[i].d>0&&f[x]+e[i].c<f[y])
{
f[y]=f[x]+e[i].c;
pre[y]=i;
if(!in[y])in[y]=true,q.push(y);
}
}
}
return(f[ed]!=1061109567);
}
int ans;
void work()
{
int now=pre[ed],mn=inf;
while(now!=-1)
{
mn=min(mn,e[now].d);
now=pre[e[now].x];
}
ans+=(f[ed]*mn);
now=pre[ed];
while(now!=-1)
{
e[now].d-=mn;e[now^1].d+=mn;
now=pre[e[now].x];
}
}
int cnt1,cnt2;
bool check(int lim)
{
memset(last,0,sizeof(last));len=1;ans=0;
for(int i=1;i<=n;i++)
{
addedge(st,i,lim,0);
addedge(i+n,ed,lim,0);
addedge(i,i+n,lim,0);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!mp[i][j])addedge(i,j+n,1,-1);
else if(mp[i][j]==2)addedge(i,j+n,1,-10001);
while(spfa())work();
ans=-ans;
return(ans/10000==cnt2&&(ans%10000)*A/B>=lim);
}
int main()
{
int Case=0;
while(1)
{
n=read(),A=read(),B=read();
if(n+A+B==0)break;
printf("Case %d: ",++Case);
cnt1=cnt2=0;int mx=0;
for(int i=1;i<=n;i++)
{
char s[42];
scanf("%s",s+1);
for(int j=1;j<=n;j++)
if(s[j]=='.')mp[i][j]=0;
else if(s[j]=='/')mp[i][j]=1,cnt1++;
else mp[i][j]=2,cnt2++;
}
for(int i=1;i<=n;i++)
{
int tmp=0;
for(int j=1;j<=n;j++)
tmp+=(mp[i][j]=='C');
mx=max(mx,tmp);
}
for(int j=1;j<=n;j++)
{
int tmp=0;
for(int i=1;i<=n;i++)
tmp+=(mp[i][j]=='C');
mx=max(mx,tmp);
}
bool flag=false;
int Ans=0;
st=(n<<1)+1,ed=(n<<1)+2;
for(int i=mx;i<=n;i++)
if(check(i)){Ans=max(Ans,ans%10000-cnt2);flag=true;}
if(!flag){puts("impossible");continue;}
printf("%d\n",Ans);
}
}