通过这个题发现了让自己的最大流模板中怀疑了两天人生的bug
本代码留下了找bug的过程中的注释
提醒自己的sb
突然又发现。。。自己写的这个模板好像不能分清正反向边
所以结构体定义要再加一个标志来分开正反向边。
#include<bits/stdc++.h>
using namespace std;
const int N = 210;
const int maxn = 210;
const int INF = 0x3f3f3f3f;
const int inf = 0x3f3f3f3f;
int st,des;
int n;
char mapp[maxn][maxn];
int a[maxn];
///终点 容量 反向边编号
struct edge
{
int to,cap,rev;
edge(int a=0,int b=0,int c=0)
{
to=a;
cap=b;
rev=c;
}
};
vector<edge>G[maxn];
int level[maxn];///顶点到源点的距离标号
int iter [maxn];///当前弧,在其之前的便已经没用了
///加边
void add_edge(int from,int to,int cap)
{
G[from].push_back(edge(to,cap,G[to].size()));
///因为G[from]添加了一个新的 所以在下面要 减1
G[to].push_back(edge(from,0,G[from].size()-1 ));
}
///初始化
void init(int z)
{
for(int i=0; i<z; i++)
G[i].clear();
}
void bfs(int s)
{
memset(level,-1,sizeof level);
queue<int>q;
level[s]=0;
q.push(s);
while(!q.empty())
{
int v=q.front();
q.pop();
for(int i=0; i<G[v].size(); i++)
{
edge &e=G[v][i];
if(e.cap>0&&level[e.to]<0)
{
///确定了远近先后关系
level[e.to]=level[v]+1;
q.push(e.to);
}
}
}
}
int dfs(int v,int t,int f)
{
///到达汇点 返回值
if(v==t||f==0)
{
//cout<<"tiqian v"<<v<<"f"<<f<<endl;
return f;
}
///用到了 引用 改变iter
for(int &i=iter[v]; i<G[v].size(); i++)
{
edge &e=G[v][i];
///正向 且还有流量
if(e.cap>0&&level[v]<level[e.to])
{//cout<<"正向且有流量 v点"<<v<<"第i条边"<<i<<"e.cap"<<e.cap<<endl;
int k=min(f,e.cap);
//if(k==1) cout<<"v: "<<v<<"i: "<<i<<endl;
int d=dfs(e.to,t,k);
//if(k==1)cout<<"asd"<<k<<endl;
if(d>0)
{
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int max_flow(int s,int t)
{
int flow=0;
while(1)
{
bfs(s);
///没有路径能够到达源点了
if(level[t]<0)
return flow;
memset(iter,0,sizeof iter);
int f;
///一遍又一遍的压榨
while(1)
{//为啥每次都是1???因为你煞笔 你写成这样 while(f=dfs(s,t,inf)>0) f当然恒等于 1 了 耽误我两个下午
f=dfs(s,t,inf);
if(f<1)break;
flow+=f;
//cout<<"f: "<<f<<endl;
}
}
}
int Build(int val)
{
int sum=0;
init(maxn);
st=0;
des=2*n+1;
for(int i=1; i<=n; i++)
{
bool isborder = false;
if(!a[i])//敌军跳过
continue;
add_edge(st,i,a[i]);//源点到入度
add_edge(i,i+n,a[i]);//入度到出度
for(int j=1; j<=n; j++)
{
if(mapp[i][j]=='Y')
{
if(!a[j])//敌军
isborder = true;
else
add_edge(i,n+j,INF);//i的入度点 和j的出度点连接
}
}
if(isborder)//属于边境
{
add_edge(i+n,des,val);//容量设置为mid
sum+=val;
}
else
{
add_edge(i+n,des,1);//至少有一个人守卫
sum+=1;
}
}
return sum;//最大满流
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=n; i++)
scanf("%s",mapp[i]+1);
//cout<<Build(50005)<<endl;
//cout<<Build(4)<<endl;
// cout<<max_flow(st,des)<<endl;
int sl=0,sr=100010;
while(sl<sr)
{
int mid=(sl+sr+1)>>1;
int val=Build(mid);
int f=max_flow(st,des);//cout<<mid<<" "<<f <<" "<<val<<endl;
//cout<<"f: "<<f<<endl;//
if(f==val)
{
sl=mid;
}
else
sr=mid-1;
}
printf("%d\n",sl);
}
return 0;
}
/*
1
7
7 3 3 2 0 0 5
NYNNNNN
YNYYNNN
NYNYYNN
NYYNYNN
NNYYNNN
NNNNNNY
NNNNNYN
*/