1. 程式人生 > >Control 網路流dinic當前弧優化

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