您的位置:首页 > 其它

HDU 3491 Thieves 【拆点+最大流】

2010-08-21 16:05 435 查看
【题目地址】

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。。(*^__^*) )代码:

【代码】

隐藏行号
复制代码
? C/C++

#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;


}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: