HDU 3491 Thieves | 最小割

来源:互联网 发布:淘宝联盟怎么做高佣 编辑:程序博客网 时间:2024/05/16 14:33

用到了之前做最大流中的一个方法,拆点。


题意:

警察要拦截小偷们,小偷在S市,警察在H市。警察不希望在S或者H城市抓获小偷。小偷进入H城市有多条路径。

给出了每个城市所需要的警察人数,表示小偷来到这个城市,需要这么多个警察才能把他们全抓起来。


思路:

想想其实跟喜羊羊那题差不多,因为都是拦截,使s与t分割开。

把每个城市分拆成两个点。

例如A城市,分拆后成为A' 和A城市。

A‘ 到 A的流量 :A城市所需要部署的人数。所有要到A城市的边全连到A’ 上,容量为INF。


#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <queue>#include <vector>using namespace std;const int INF = 0x3f3f3f3f;const int MAXEDGE = 5*1e5 + 5;const int MAXN = 255;int peo[MAXN];int n, m, s, h;struct Edge{        int to, cap, flow, next;}edge[MAXEDGE];struct Dinic{        int pp, s, t;        int head[MAXN], cur[MAXN];        bool vis[MAXN];        int d[MAXN];        Dinic(int ss, int tt)        {                s = ss, t = tt;                pp = 0;                memset(head, -1, sizeof(head));        }        void addEdge(int u, int v, int c)        {                edge[pp] = (Edge){v, c, 0, head[u]};                head[u] = pp++;                edge[pp] = (Edge){u, 0, 0,head[v]};                head[v] = pp++;        }        int getMaxFlow()        {                int res = 0;                while(bfs())                {                    for(int i = 1;i <= 2*n + 5; i++)                        cur[i] = head[i];                    //cout<<"res = "<<res<<endl;                    res += dfs(s, INF);                }                return res;        }        bool bfs()        {                memset(vis, false, sizeof(vis));                d[s] = 0;                vis[s] = true;                queue <int> q;                q.push(s);                while(!q.empty())                {                        int u = q.front();                        q.pop();                        int next = head[u];                        while(next != -1)                        {                                Edge &e = edge[next];                                if(!vis[e.to] && e.cap > e.flow)                                {                                        d[e.to] = d[u] + 1;                                        vis[e.to] = true;                                        q.push(e.to);                                }                                next = e.next;                        }                }                return vis[t];        }        int dfs(int u, int a)        {                if(u == t || a == 0)    return a;                int &next = cur[u];                int flow = 0, f;                while(next != -1)                {                        Edge &e = edge[next];                        if(d[e.to] == d[u] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)                        {                                e.flow += f;                                edge[next^1].flow -= f;                                flow += f;                                a -= f;                                if(a == 0)      break;                        }                        next = e.next;                }                //cout<<"flow = "<<flow<<endl;                return flow;        }};int main(){        int t;        cin>>t;        while(t--)        {               scanf("%d%d%d%d",&n, &m, &s, &h);               Dinic dinic(s, h);               for(int i = 1;i <= n; i++)               {                       scanf("%d",&peo[i]);               }               //build               for(int i = 1;i <= n; i++)               {                       if(i == s || i == h)                       {                               dinic.addEdge(i + n, i, INF);                               continue;                       }                       dinic.addEdge(i + n, i, peo[i]);               }               int u, v;               for(int i = 0;i < m; i++)               {                       scanf("%d%d", &u, &v);                       dinic.addEdge(u, v + n, INF);                       dinic.addEdge(v, u + n, INF);               }               printf("%d\n",dinic.getMaxFlow());        }        return 0;}






0 0