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++
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;
}
相关文章推荐
- hdu 3491 Thieves 最小割
- HDU 3491 Thieves(经典拆点建图,割点)
- HDU 3491 Thieves 最小点割集+拆点==最大流(建图可贵)
- 【HDU】3491 Thieves 最小点割集
- hdu 3491 Thieves(最小割)
- hdu 3491 Thieves
- HDU 3491 Thieves 拆点 最小割
- hdu 3491 Thieves
- HDU 3491 Thieves 网络流,拆点,最小割模型
- [HDU] 3491 Thieves
- hdu 3491 Thieves
- Thieves (hdu 3491 拆点 最小割)
- hdu 3491 Thieves(最小割拆点)
- HDU 3491 Thieves
- hdu 1003/poj 1050 连续子序列最大和经典基础dp
- hdu 1754 I Hate It(线段树求最大值)
- Graph Theory NO.9 HDU_1532_Drainage Ditches_最大流
- HDU 1754 求区间的最大值
- hdu 2255二分图最大权值匹配的KM 算法
- hdu 3996 Gold Mine (最大权闭合子图)