Control 网络流dinic当前弧优化

题目:

You, the head of Department of Security, recently received a top-secret information that a group of terrorists is planning to transport some WMD 1 from one city (the source) to another one (the destination). You know their date, source and destination, and they are using the highway network. 
  The highway network consists of bidirectional highways, connecting two distinct city. A vehicle can only enter/exit the highway network at cities only. 
  You may locate some SA (special agents) in some selected cities , so that when the terrorists enter a city under observation (that is, SA is in this city), they would be caught immediately. 
  It is possible to locate SA in all cities, but since controlling a city with SA may cost your department a certain amount of money, which might vary from city to city, and your budget might not be able to bear the full cost of controlling all cities, you must identify a set of cities, that: 
  * all traffic of the terrorists must pass at least one city of the set. 
  * sum of cost of controlling all cities in the set is minimal. 
  You may assume that it is always possible to get from source of the terrorists to their destination. 
--------------------------------------- --------------------- 
1 Weapon of Mass Destruction

输入:

There are several test cases. 
  The first line of a single test case contains two integer N and M ( 2 <= N <= 200; 1 <= M <= 20000), the number of cities and the number of highways. Cities are numbered from 1 to N. 
  The second line contains two integer S,D ( 1 <= S,D <= N), the number of the source and the number of the destination. 
  The following N lines contains costs. Of these lines the ith one contains exactly one integer, the cost of locating SA in the ith city to put it under observation. You may assume that the cost is positive and not exceeding 10 7 . 
  The followingM lines tells you about highway network. Each of these lines contains two integers A and B, indicating a bidirectional highway between A and B. 
  Please process until EOF (End Of File).

输出:

 For each test case you should output exactly one line, containing one integer, the sum of cost of your selected set. 
  See samples for detailed information.

样例输入:

5 6
5 3
5
2
3
4
12
1 5
5 4
2 3
2 4
4 3
2 1

样例输出:

3

题意:一群恐怖分子要从一个源城市送到一个目的地城市。我们可以在某些城市找一些特工来抓他们,每个城市的特工需要花费的费用不一样。恐怖分子的所有交通必须通过至少一个城市的集合,要保证所花费的费用之和最小。最小割等于最大流,最后还是求最大流。对于拆点,要把一个点拆成两个点,另一个点必须在之前的数据中没有出现过。所以我们把每一个点i拆成i,i+n。这几个点的入点到出点就是所给的费用,从出点到入点就是0。 对于相连的点,相互之间都是  I 点的出点到 J 点的入点流为最大 ,J 点的入点到 I 点的出点流为0,将 I 点和 J 点对换再建一次

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=200005;
const int N=405;
int s,d,cnt;
int T;
int dis[N],head[N],cur[N];
struct edge
{
    int u,v,c,next;
}node[maxn];
void add(int u,int v,int c)
{
    node[cnt].v=v;
    node[cnt].c=c;
    node[cnt].next=head[u];
    head[u]=cnt++;
}
int bfs()
{
    memset(dis,0,sizeof(dis));
    queue<int>q;
    q.push(s);
    dis[s]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=node[i].next)
        {
            edge e= node[i];
            if(!dis[e.v]&&e.c>0)
             {
                dis[e.v]=dis[u]+1;
                q.push(e.v);
                if(e.v == T) return 1;
            }
        }
    }
    return dis[T]!=0;
}
int dfs(int u,int mx)
{
    int ret = 0;
    if(u==T || mx == 0)return mx;
    for(int &i=cur[u];i!=-1;i=node[i].next)//当前弧优化
    {
        edge e=node[i];
        if(dis[e.v]==dis[u]+1&&e.c>0)
        {
            int w=dfs(e.v,min(mx,e.c));

            node[i].c-=w;
            node[i^1].c+=w;
            ret += w;//ret是把每一条路径的w都加起来(通过一次bfs得到的增广路不止一条)
            mx -= w;
            if(mx == 0) break;
        }
    }
   return ret;
}
int dinic()
{
    int maxflow=0;
    while(bfs())//找增广路,第一次通过bfs得到的流我们不能确定他就是最大流,要继续对残留网络进            
                //行bfs
    {
            memcpy(cur,head,sizeof(head));
            maxflow+= dfs(s, INF);
    }
    return maxflow;
}
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        scanf("%d %d",&s,&d);
        cnt=0;
        memset(head,-1,sizeof(head));

        for(int i=1;i<=n;i++)
        {
            int a;
            scanf("%d",&a);
            add(i,i+n,a);
            add(i+n,i,0);

        }
        while(m--)
        {
            int i,j;
            scanf("%d %d",&i,&j);
            add(i+n,j,INF);
            add(j,i+n,0);
            add(j+n,i,INF);
            add(i,j+n,0);
        }
        T=d+n;
        printf("%d\n",dinic());
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值