zoukankan      html  css  js  c++  java
  • HDU4289 Control

      原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=4289

      网络流,最大流 + 拆点。

      最大流:sap算法

      常用的两种拆点方式:

        1. 对于每个节点id,拆成 id<<1 和 id<<1|1 两个点

        2.对于每个节点id,拆成 id 和 id+n 两个点

    View Code
      1 #include <stdio.h>
      2 #include <string.h>
      3 #define L(u) ((u) << 1)
      4 #define R(u) ((u) << 1 | 1)
      5 #define N 420
      6 #define M 100000
      7 #define INF 0x3f3f3f3f
      8 
      9 int gap[N],dis[N],pre[N],cur[N];
     10 int n,m,NE, s, t;
     11 int head[N];
     12 struct Node{
     13     int c,pos,next;
     14 }E[M];
     15 
     16 inline void checkmin(int &a,int b)  {if(a == -1 || a > b)a = b;}
     17 
     18 void add_edge(int u,int v,int c)
     19 {
     20     E[NE].c = c;
     21     E[NE].pos = v;
     22     E[NE].next = head[u];   
     23     head[u] = NE++;
     24     
     25     E[NE].c = 0;    // !反向初始为0
     26     E[NE].pos = u;
     27     E[NE].next = head[v];   
     28     head[v] = NE++;
     29 }
     30 
     31 int sap()
     32 {
     33     memset(dis,0,sizeof dis);
     34     memset(gap,0,sizeof gap);
     35     memcpy (cur, head, sizeof dis);
     36     int u=pre[s]=s,maxflow=0,aug=-1;
     37     gap[0]=n;
     38     while(dis[s]<n)
     39     {
     40 loop:for(int &i=cur[u];i!=-1;i=E[i].next)
     41         {
     42             int v=E[i].pos;
     43             if(E[i].c && dis[u]==dis[v]+1)
     44             {
     45                 checkmin(aug, E[i].c);
     46                 pre[v]=u;
     47                 u=v;
     48                 if(v==t)
     49                 {
     50                     maxflow+=aug;
     51                     for(u=pre[u];v!=s;v=u,u=pre[u])
     52                     {
     53                         E[cur[u]].c-=aug;
     54                         E[cur[u]^1].c+=aug;
     55                     }
     56                     aug=-1;
     57                 }
     58                 goto loop;
     59             }
     60         }
     61         int mindis=n;
     62         for(int i=head[u];i!=-1;i=E[i].next)
     63         {
     64             int v=E[i].pos;
     65             if(E[i].c && mindis>dis[v])
     66             {
     67                 cur[u]=i;
     68                 mindis=dis[v];
     69             }
     70         }
     71         if((--gap[dis[u]])==0) break;
     72         gap[dis[u]=mindis+1]++;
     73         u=pre[u];
     74     }
     75     return maxflow;
     76 }
     77  
     78 void init()
     79 {
     80     memset(head, -1, sizeof head);
     81     NE = 0;
     82 }
     83  
     84 int main()
     85 {
     86     int i, a, b, w;
     87     while(scanf("%d%d", &n, &m) != EOF)
     88     {
     89         init();
     90         scanf("%d%d", &s, &t);
     91         add_edge(0, L(s), INF);          // 0为超级源点
     92         add_edge(R(t), R(n + 1), INF);   // R(n + 1)为超级汇点
     93         s = 0;
     94         t = R(n + 1);
     95         for(i = 1; i <= n; i ++)
     96         {
     97             scanf("%d", &w);
     98             add_edge(L(i), R(i), w);
     99             add_edge(R(i), L(i), w); 
    100         }
    101         for(i = 0; i < m; i ++)
    102         {
    103             scanf("%d%d", &a, &b);
    104             add_edge(R(a), L(b), INF);
    105             add_edge(R(b), L(a), INF);
    106         }
    107         n = 2 * (n + 1);                 // 总节点数的变化
    108         printf("%d\n", sap());
    109     }
    110     return 0;
    111 }

       

  • 相关阅读:
    JS站点
    1011 World Cup Betting (20分)
    1007 Maximum Subsequence Sum (25分)(动态规划DP)
    1006 Sign In and Sign Out (25分)
    1005 Spell It Right (20分)
    1004 Counting Leaves (30分)(DFS)
    1003 Emergency (25分)(Dijkstra算法)
    1002 A+B for Polynomials (25分)
    1001 A+B Format (20分)
    canvas
  • 原文地址:https://www.cnblogs.com/huangfeihome/p/2694519.html
Copyright © 2011-2022 走看看