構圖的思路與POJ 2391是一樣的,對於從一個初級源點s出發的流,如果可到達的點是受限制的,可以先把這些受限制的點都找出來,拆點拆成i->i',然後,s向i'連邊,
最後,超級源點S向每個初級源點s連邊,每個點i'向匯點連邊
爲什麼要這麼做?因爲既然從s出發的流是受限制的,我們可以在s上限制它,但也必須在每個s可到的點上限制它,而網絡流中是不分這部分流是從哪個源點過來的,因此,無法在下面的點上限制該流,那麼,我們必須採取某種策略,使得該流從s出發後不會走到限制範圍外的點,方法就是處理出所有受限制的點,直接連邊,並且,這些流只能到達匯點
一組不這麼做會錯的數據
5 1
0YZ52
3Y481
66Y68
Y1665
35923
9YZ89
2Y876
08Y19
Y1891
24689
答案是88,不這麼拆點答案就是89,在這裏wa了很久
另外,這道題還要預先處理出爆炸點到每個實驗室的最短路,以及每個有科學家的實驗室到所有具有救生艙的實驗室的最短路,如果實驗室a到實驗室b的最短路徑小於等於爆炸點到實驗室b的最短路徑,就可以連邊a->b'
由於邊權爲1,可以用bfs實現
代碼:
#include<iostream>
#include<memory.h>
#include<string>
#include<cstdio>
#include<algorithm>
#include<math.h>
#include<stack>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int MAX=10005;
const int inf=1<<30;
struct node
{
int u,v,c,next;
}g[MAX*10];
struct Node
{
int x,y,step;
};
int adj[MAX],dis[MAX],cur[MAX],pre[MAX],num[MAX],n,e,s,t,vn,T;
int sx,sy,dir[4][2]={1,0,-1,0,0,1,0,-1};
int flag[15][15],vis[15][15];
char mat1[15][15],mat2[15][15];
bool in(int x,int y)
{
if(x<1||x>n||y<1||y>n)
return false;
return true;
}
void add(int u,int v,int c)
{
g[e].u=u; g[e].v=v; g[e].c=c; g[e].next=adj[u]; adj[u]=e++;
g[e].u=v; g[e].v=u; g[e].c=0; g[e].next=adj[v]; adj[v]=e++;
//if(u==s||v==t)
//if(u==12+n*n&&v==17)
//cout<<u<<" "<<v<<" "<<c<<endl;
}
void bfs1()
{
queue<Node>que;
Node now,next;
now.x=sx; now.y=sy; now.step=0;
que.push(now);
memset(flag,0x7f,sizeof(flag));
memset(vis,0,sizeof(vis));
vis[now.x][now.y]=1;
while(!que.empty())
{
now=que.front();
que.pop();
flag[now.x][now.y]=now.step;
if(now.step>T)
break;
for(int i=0;i<4;i++)
{
int xx=now.x+dir[i][0];
int yy=now.y+dir[i][1];
if(in(xx,yy)&&mat1[xx][yy]!='Y'&&!vis[xx][yy])
{
next.x=xx; next.y=yy; next.step=now.step+1;
vis[xx][yy]=1;
que.push(next);
}
}
}
}
void bfs2(int i,int j)
{
queue<Node>que;
Node now,next;
now.x=i; now.y=j; now.step=0;
que.push(now);
memset(vis,0,sizeof(vis));
vis[now.x][now.y]=1;
while(!que.empty())
{
now=que.front();
que.pop();
if(now.step>T)
break;
if(flag[now.x][now.y]<now.step)
continue;
if(flag[now.x][now.y]==now.step&&(mat2[now.x][now.y]<'1'||mat2[now.x][now.y]>'9'))
continue;
if(mat2[now.x][now.y]>='1'&&mat2[now.x][now.y]<='9')
{
if(now.x!=i||now.y!=j)
add((i-1)*n+j,(now.x-1)*n+now.y+n*n,inf);
if(flag[now.x][now.y]==now.step)
continue;
}
for(int i=0;i<4;i++)
{
int xx=now.x+dir[i][0];
int yy=now.y+dir[i][1];
if(in(xx,yy)&&mat1[xx][yy]!='Y'&&!vis[xx][yy])
{
next.x=xx; next.y=yy; next.step=now.step+1;
vis[xx][yy]=1;
que.push(next);
}
}
}
}
int sap()
{
int i,u,v,flag,aug=inf,flow=0;
for(i=0;i<=vn;i++)
{
cur[i]=adj[i];
num[i]=dis[i]=0;
}
num[0]=vn;
pre[s]=u=s;
while(dis[s]<vn)
{
flag=0;
for(i=cur[u];i!=-1;i=g[i].next)
{
v=g[i].v;
if(g[i].c&&dis[u]==dis[v]+1)
{
flag=1;
aug=min(aug,g[i].c);
pre[v]=u;
cur[u]=i;
u=v;
if(u==t)
{
flow+=aug;
while(u!=s)
{
u=pre[u];
g[cur[u]].c-=aug;
g[cur[u]^1].c+=aug;
}
aug=inf;
}
break;
}
}
if(flag)
continue;
if(--num[dis[u]]==0)
break;
for(dis[u]=vn,i=adj[u];i!=-1;i=g[i].next)
{
v=g[i].v;
if(g[i].c&&dis[v]<dis[u])
{
dis[u]=dis[v];
cur[u]=i;
}
}
dis[u]++;
num[dis[u]]++;
u=pre[u];
}
return flow;
}
int main()
{
int i,j,k;
while(scanf("%d%d",&n,&T)!=EOF)
{
memset(adj,-1,sizeof(adj));
e=0;
s=0;
t=n*n+n*n+1;
vn=t+1;
for(i=1;i<=n;i++)
{
scanf("%s",mat1[i]+1);
for(j=1;j<=n;j++)
{
if(mat1[i][j]>='1'&&mat1[i][j]<='9')
{
add(s,(i-1)*n+j,mat1[i][j]-'0');
}
if(mat1[i][j]=='Z')
{
sx=i;
sy=j;
}
}
}
for(i=1;i<=n;i++)
{
scanf("%s",mat2[i]+1);
for(j=1;j<=n;j++)
{
add((i-1)*n+j,(i-1)*n+j+n*n,inf);
if(mat2[i][j]>='1'&&mat2[i][j]<='9')
add((i-1)*n+j+n*n,t,mat2[i][j]-'0');
}
}
bfs1();
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(mat1[i][j]>='1'&&mat1[i][j]<='9')
bfs2(i,j);
}
}
i=1;
printf("%d\n",sap());
/*for(i=1;i<=100;i++)
{
for(j=adj[i];j!=-1;j=g[j].next)
{
if(g[j].v==t)
printf("%d %d\n",i,g[j^1].c);
}
} */
/*for(i=1;i<e;i+=2)
{
if(g[i].u==g[i].v+n*n)
continue;
printf("%d %d %d\n",g[i].v>n*n?g[i].v-n*n:g[i].v,g[i].u>n*n?g[i].u-n*n:g[i].u,g[i].c);
} */
}
return 0;
}