题意:给你一个图,图上.,#,P,S,H分别代表可行区域,不可行区域,公园,学校,房子,再给你一个距离D,要求你所卖出的房子必须要一个公园和一个学校,这俩距离你所卖的房子不超过D
算法:dinic 将图拆成n个点,源点等于0,汇点等于2*n;
将房子拆成俩个点分别连接公园,学校
# include <bits/stdc++.h>
using namespace std;
#define f first
#define s second
# define int long long
int l,c,D;
int s1,t;
const int inf=1<<29;
const int N=1000;
int dist[N][N];
int ids[N][N];
char m[N][N];
int varx[]= {0,0,1,-1};
int vary[]= {1,-1,0,0};
vector<pair<int,int>>house;
const int N1=50010,M=300010;
int ver[M],head[M],Next[M],edge[M];
int d[N1];
int tot=1;
void add(int x,int y,int z) {
ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
ver[++tot]=x,edge[tot]=0,Next[tot]=head[y],head[y]=tot;
}
int now[M];
bool bfs() {
memset(d,0,sizeof(d));
queue<int>q;
while(q.size()) {
q.pop();
}
q.push(s1);
d[s1]=1;
now[s1]=head[s1];
while(q.size()) {
int x=q.front();
q.pop();
for(int i=head[x]; i; i=Next[i]) {
if(edge[i]&&!d[ver[i]]) {
q.push(ver[i]);
now[ver[i]]=head[ver[i]];
d[ver[i]]=d[x]+1;
if(ver[i]==t) {
return 1;
}
}
}
}
return 0;
}
int dinic(int x,int flow) {
if(x==t) {
return flow;
}
int rest=flow,k,i;
for(i=now[x]; i&&rest; i=Next[i]) {
now[x]=i;
if(edge[i]&&d[ver[i]]==d[x]+1) {
k=dinic(ver[i],min(rest,edge[i]));
if(!k) {
d[ver[i]]=0;
}
edge[i]-=k;
edge[i^1]+=k;
rest-=k;
}
}
return flow-rest;
}
void bfs1(int i,int j) {
queue<pair<int,int>>q;
q.push({i,j});
dist[i][j]=0;
while(!q.empty()) {
auto x=q.front();
q.pop();
for(int k=0; k<4; k++) {
int x1=x.f+varx[k];
int y1=x.s+vary[k];
if(m[x1][y1]=='S'||m[x1][y1]=='P') {
if(dist[x1][y1]==-1) {
dist[x1][y1]=1+dist[x.f][x.s];
}
continue ;
}
if(x1<1||x1>l||y1<1||y1>c||dist[x1][y1]!=-1||m[x1][y1]!='.') {
continue ;
}
dist[x1][y1]=dist[x.f][x.s]+1;
q.push({x1,y1});
}
}
}
signed main() {
cin>>l>>c>>D;
int cnt=0;
for(int i=1; i<=l; i++) {
for(int j=1; j<=c; j++) {
cin>>m[i][j];
ids[i][j]=++cnt;
if(m[i][j]=='H') {
house.push_back({i,j});
}
}
}
int n=++cnt;
for(int i=1; i<=l; i++) {
for(int j=1; j<=c; j++) {
if(m[i][j]=='P')
{
add(ids[i][j],2*n,1);
}
else if(m[i][j]=='S')
{
add(0,ids[i][j],1);
}
}
}
for(auto x: house)
{
memset(dist,-1,sizeof(dist));
bfs1(x.f,x.s);
add(ids[x.f][x.s],ids[x.f][x.s]+n,1);
for(int i=1;i<=l;i++)
{
for(int j=1;j<=c;j++)
{
if(m[i][j]=='S'&&dist[i][j]!=-1&&dist[i][j]<=D)
{
add(ids[i][j],ids[x.f][x.s],1);
}
if(m[i][j]=='P'&&dist[i][j]!=-1&&dist[i][j]<=D)
{
add(ids[x.f][x.s]+n,ids[i][j],1);
}
}
}
}
n*=2;
s1=0;
t=n;
int flow=0;
int maxflow=0;
while(bfs())
{
while(flow=dinic(s1,inf))
{
maxflow+=flow;
}
}
cout<<maxflow<<endl;
}