【題目地址】
http://acm.hdu.edu.cn/showproblem.php?pid=3491
【題目大意】
有n個城市和m條道路(雙向),一夥thieves準備從S城出發到H城盜竊,The brave, brilliant, bright police(囧!!)爲了將這夥thieves抓住,需要在這n個城市中的每一個城市安排一定數量的police(已知條件)。但police不希望在S城或H城邂逅thieves。
求總共需要的最少police數。
【解題思路】
把城市作爲點拆開(把城市 i 拆成cap數組中的cap[i][i+n].其中i作爲城市i的入,i+n作爲城市i的出),原來的道路仍然作爲邊,但是邊權是無窮大. 只要注意到BFS的時候 起點/終點是不需要拆的.(在cap[][]數組中就直接把起點/終點的入和出之間的邊權賦值爲0,使得BFS的時候不走起點/終點,實際上就相當於沒有把起點/終點拆開.程序中的處理方法就是 cap[s][s+n] = 0;/cap[e][e+n] = 0;)
PS(與本題無關):HDU 3549(最大流)WA了n次,才知道兩點之間可能有多條道路,cap[][]爲邊權之和。
題目n<=100,m<=10000,建議用SAP或Dinic求最大流,時間複雜度爲O(V^2 * E)。
本題數據較弱,下面是O(V*E^2)的樸素層次圖算法(實際上就是BFS。。(*^__^*) )代碼:
【代碼】
-
#include<cstdio>
-
#include<cstring>
-
#define inf 2147483647
-
#define maxn 201
-
int cap[maxn][maxn],que[maxn],pre[maxn],vis[maxn];
-
int s,t,n,m,h;
-
bool bfs()
-
{
-
int i,j,l=0,r=0;
-
que[r++]=s;
-
memset(vis,0,sizeof(vis));
-
while(l<r)
-
{
-
j=que[l++];
-
for(i=1;i<=2*n;i++)
-
if(!vis[i]&&cap[j][i]>0)
-
{
-
vis[i]=1;
-
pre[i]=j;
-
if(i==t)
-
return true;
-
que[r++]=i;
-
}
-
}
-
return false;
-
}
-
int maxflow()
-
{
-
int flow=0,i,min;
-
while(bfs())
-
{
-
for(i=t,min=inf;i!=s;i=pre[i])
-
if(cap[pre[i]][i]<min)
-
min=cap[pre[i]][i];
-
flow+=min;
-
for(i=t; i!=s;i=pre[i])
-
{
-
cap[pre[i]][i]-=min;
-
cap[i][pre[i]]+=min;
-
}
-
}
-
return flow;
-
}
-
int main()
-
{
-
int T,x,y,i;
-
scanf("%d", &T);
-
while(T--)
-
{
-
memset(cap,0,sizeof(cap));
-
scanf("%d%d%d%d",&n,&m,&s,&h);
-
for(i=1;i<=n;i++)
-
scanf("%d",&cap[i][i+n]);
-
s=s+n;t=h;
-
cap[h][h+n]=0;
-
cap[s][s+n]=0;
-
for(i=1;i<=m;i++)
-
{
-
scanf("%d%d",&x,&y);
-
cap[x+n][y]=inf;
-
cap[y+n][x]=inf;
-
}
-
printf("%d/n",maxflow());
-
}
-
return 0;
-
}