3 YYY NYY YNY 2 YN YN 0
2 3 1 2 1 2 3 0
二分答案网络流,求出k.
删除多余边,
接下来k次,
每次在原图上找最大二分图匹配,删除边,
得到一个可行解
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
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 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 (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXn (80+10)
#define MAXN (500+19)
#define MAXM (69999+100)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
class Max_flow //dinic+当前弧优化
{
public:
int n,s,t;
int q[MAXN];
int edge[MAXM],next[MAXM],pre[MAXN],weight[MAXM],size;
void addedge(int u,int v,int w)
{
edge[++size]=v;
weight[size]=w;
next[size]=pre[u];
pre[u]=size;
}
void addedge2(int u,int v,int w){addedge(u,v,w),addedge(v,u,0);}
bool b[MAXN];
int d[MAXN];
bool SPFA(int s,int t)
{
For(i,n) d[i]=INF;
MEM(b)
d[q[1]=s]=0;b[s]=1;
int head=1,tail=1;
while (head<=tail)
{
int now=q[head++];
Forp(now)
{
int &v=edge[p];
if (weight[p]&&!b[v])
{
d[v]=d[now]+1;
b[v]=1,q[++tail]=v;
}
}
}
return b[t];
}
int iter[MAXN];
int dfs(int x,int f)
{
if (x==t) return f;
Forpiter(x)
{
int v=edge[p];
if (weight[p]&&d[x]<d[v])
{
int nowflow=dfs(v,min(weight[p],f));
if (nowflow)
{
weight[p]-=nowflow;
weight[p^1]+=nowflow;
return nowflow;
}
}
}
return 0;
}
int max_flow(int s,int t)
{
int flow=0;
while(SPFA(s,t))
{
For(i,n) iter[i]=pre[i];
int f;
while (f=dfs(s,INF))
flow+=f;
}
return flow;
}
void mem(int n,int s,int t)
{
(*this).n=n;
(*this).t=t;
(*this).s=s;
size=1;
MEM(pre)
}
}S;
char s[MAXn][MAXn];
int n;
bool check(int m)
{
S.mem(2*n+2,1,2*n+2);
For(i,n) S.addedge2(1,i+1,m),S.addedge2(n+1+i,2*n+2,m);
For(i,n) For(j,n) if (s[i][j]=='Y') S.addedge2(1+i,n+1+j,1);
if (S.max_flow(1,2*n+2)==n*m) return 1;
return 0;
}
int Ans[MAXn];
int main()
{
// freopen("hdu4265.in","r",stdin);
// freopen(".out","w",stdout);
while(scanf("%d",&n)==1)
{
if (!n) break;
For(i,n) scanf("%s",s[i]+1);
int l=0,r=n,ans=0;
while(l<=r)
{
int m=(l+r)>>1;
if (check(m)) ans=m,l=m+1;
else r=m-1;
}
check(ans);
printf("%d\n",ans);
Fork(i,2,n+1)
{
for(int p=S.pre[i];p;p=S.next[p])
if (!S.weight[p^1]&&S.edge[p]>n+1) s[i-1][S.edge[p]-n-1]='N';
}
while (ans--)
{
S.mem(2*n+2,1,2*n+2);
For(i,n) S.addedge2(1,i+1,1),S.addedge2(n+1+i,2*n+2,1);
For(i,n) For(j,n) if (s[i][j]=='Y') S.addedge2(1+i,n+1+j,1);
S.max_flow(1,2*n+2);
Fork(i,2,n+1)
{
for(int p=S.pre[i];p;p=S.next[p])
if (!S.weight[p]&&S.edge[p]>n+1)
{
Ans[S.edge[p]-n-1]=i-1,s[i-1][S.edge[p]-n-1]='N';
break;
}
}
For(i,n-1) printf("%d ",Ans[i]);printf("%d\n",Ans[n]);
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/nike0good/article/details/47622741