zoukankan      html  css  js  c++  java
  • 【板子】网络流

    最大流:

    例题:http://poj.org/problem?id=1273

    dinic:

     1 //dinic
     2 
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <string.h>
     6 #include <cstdio>
     7 #include <queue>
     8 using namespace std;
     9 const int inf = 0x3f3f3f3f;
    10 const int maxn = 205;
    11 const int maxm = maxn*maxn;
    12 struct node{int w; int v, next;} edge[maxm];
    13 int pre[maxn], rec[maxn], head[maxn], block[maxn];
    14 int dis[maxn];
    15 int n, m, no;
    16 int S, T;
    17 queue<int> q;
    18 inline void init(){
    19     no = 0;
    20     memset(head, -1, sizeof head);
    21 }
    22 inline void add(int u, int v, int w){
    23     edge[no].v = v; edge[no].w = w;
    24     edge[no].next = head[u]; head[u] = no++;
    25     edge[no].v = u; edge[no].w = 0;
    26     edge[no].next = head[v]; head[v] = no++;
    27 }
    28 void reset(int S, int T){
    29     memset(dis, 0x3f, sizeof dis);
    30     memset(block, 0, sizeof block);
    31     q.push(S); dis[S] = 0;
    32     while(!q.empty()){
    33         int top = q.front(); q.pop();
    34         for(int k = head[top]; k != -1; k = edge[k].next)
    35         if(dis[edge[k].v] == inf && edge[k].w)
    36             dis[edge[k].v] = dis[top]+1, q.push(edge[k].v);
    37     }
    38 }
    39 int dinic(int S, int T){
    40     int ans = 0, flow = inf;
    41     int top = S;
    42     reset(S, T); pre[S] = S;
    43     while(dis[T] != inf){
    44         int k, tmp;
    45         for(k = head[top]; k != -1; k = edge[k].next){
    46             if(edge[k].w && dis[edge[k].v]==dis[top]+1 && 
    47             !block[edge[k].v]) break;
    48         }
    49         if(k != -1){
    50             tmp = edge[k].v;
    51             flow = min(flow, edge[k].w);
    52             pre[tmp] = top, rec[tmp] = k;
    53             top = tmp;
    54             if(top == T){
    55                 ans += flow; tmp = -1;
    56                 for(; top != S; top = pre[top]){
    57                     edge[rec[top]].w -= flow;
    58                     edge[rec[top]^1].w += flow;
    59                     if(!edge[rec[top]].w) tmp = top;
    60                 }
    61                 flow = inf;
    62                 if(tmp != -1){
    63                     top = pre[tmp];
    64                     for(; top != S; top = pre[top])
    65                     flow = min(flow, edge[rec[top]].w);
    66                     top = pre[tmp];
    67                 }
    68             }
    69         }
    70         else{
    71             block[top] = 1;
    72             top = pre[top];
    73             if(block[S]) reset(S, T);
    74         }
    75     }
    76     return ans;
    77 }
    78 void mapping(){
    79     int u, v, w;
    80     for(int i = 1; i <= m; ++i){
    81         scanf("%d %d %d", &u, &v, &w);
    82         add(u, v, w);
    83     }
    84 }
    85 int main(){
    86     while(~scanf("%d %d", &m, &n)){
    87         S = 1, T = n;
    88         init();
    89         mapping();
    90         printf("%d
    ", dinic(S, T));
    91     }
    92     return 0;
    93 }

    sap:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<cstdlib>
      6 #include<string>
      7 #include<queue>
      8 #include<algorithm>
      9 using namespace std;
     10  
     11 const int N=100010;
     12 const int M=400010;
     13 const int inf=0xfffffff;
     14  
     15 int n,m,cnt;
     16  
     17 struct Edge{
     18     int v , cap , next;
     19 } edge[M];
     20  
     21 int head[N],pre[N],d[N],numd[N];//分别为链表的头指针,每个点的前驱,每个点的d值,以及标号为d[i] 的点的个数
     22 int cur_edge[N];//从每个点出发满足d[i] = d[j] + 1的边的地址 , 插入边时的计数,源点与汇点
     23  
     24 void addedge(int u,int v,int c){
     25  
     26     edge[cnt].v = v;
     27     edge[cnt].cap = c;
     28     edge[cnt].next = head[u];
     29     head[u] = cnt++;
     30  
     31     edge[cnt].v = u;
     32     edge[cnt].cap = 0;
     33     edge[cnt].next = head[v];
     34     head[v] = cnt++;
     35 }
     36  
     37 void bfs(int s){    //先用广度优先算出每个点的d值
     38     memset(numd,0,sizeof(numd));
     39     for(int i=1; i<=n; i++)
     40         numd[ d[i] = n ]++;
     41     d[s] = 0;
     42     numd[n]--;
     43     numd[0]++;
     44     queue<int> Q;
     45     Q.push(s);
     46  
     47     while(!Q.empty()){
     48         int v=Q.front();
     49         Q.pop();
     50  
     51         int i=head[v];
     52         while(i != -1){
     53             int u=edge[i].v;
     54  
     55             if(d[u]<n){
     56                 i=edge[i].next;
     57                 continue ;
     58             }
     59  
     60             d[u]=d[v]+1;
     61             numd[n]--;
     62             numd[d[u]]++;
     63             Q.push(u);
     64             i=edge[i].next;
     65         }
     66     }
     67 }
     68 
     69 int SAP(int s,int t){
     70     for(int i = 1; i <= n; i++)
     71         cur_edge[i] = head[i];   //当前满足d[i] = d[j] + 1的边的为第一条边
     72     int max_flow=0;
     73     bfs(t);
     74     int u = s ;//从源点搜一条到汇点的增广路
     75     while(d[s]<n){//就算所有的点连成一条线源点的d值也是最多是n-1
     76         if(u == t){//如果找到一条增广路径
     77             int cur_flow = inf,neck;//找到那条瓶颈边
     78             for(int from = s; from != t; from = edge[cur_edge[from]].v){
     79                 if(cur_flow > edge[cur_edge[from]].cap){
     80                     neck = from;
     81                     cur_flow = edge[cur_edge[from]].cap;
     82                 }
     83             }
     84  
     85             for(int from = s; from != t; from = edge[cur_edge[from]].v){    //修改增广路上的边的容量
     86                 int tmp = cur_edge[from];
     87                 edge[tmp].cap -= cur_flow;
     88                 edge[tmp^1].cap += cur_flow;
     89             }
     90             max_flow += cur_flow;//累加计算最大流
     91             u = neck;//下一次搜索直接从瓶颈边的前一个节点搜起
     92         }
     93  
     94         int i;
     95         for(i = cur_edge[u]; i != -1; i = edge[i].next) //从当前点开始找一条允许弧
     96             if(edge[i].cap && d[u] == d[edge[i].v]+1)//如果找到跳出循环
     97                 break;
     98  
     99         if(i!=-1){//找到一条允许弧
    100             cur_edge[u] = i;//从点u出发的允许弧的地址
    101             pre[edge[i].v] = u;//允许弧上下一个点的前驱为u
    102             u = edge[i].v;//u变成下一个点继续搜直到搜出一条增广路
    103         }
    104         else{//如果没有搜到允许弧
    105             numd[d[u]]--; //d[u]将被修改所以numd[d[u]]减一
    106             if(!numd[d[u]]) break;  //如果没有点的d值为d[u]则不可能再搜到增广路结束搜索
    107             cur_edge[u] = head[u];  //当前点的允许弧为第一条边
    108             int tmp = n;
    109             for(int j = head[u]; j != -1; j = edge[j].next) //搜与u相连的点中d值最小的
    110                 if(edge[j].cap && tmp > d[edge[j].v])
    111                     tmp = d[edge[j].v];
    112  
    113             d[u] = tmp+1; //修改d[u]
    114             numd[d[u]]++;
    115             if(u != s)
    116                 u = pre[u];//从u的前驱搜,因为从u没有搜到允许弧
    117         }
    118     }
    119     return max_flow;
    120 }
    121 inline void pre_init(){ 
    122     cnt = 0;
    123     memset(head, -1, sizeof head);  
    124 } 
    125 
    126 void mapping(){
    127     int u, v, w;
    128     for(int i = 1; i <= m; ++i){  
    129         scanf("%d %d %d", &u, &v, &w); 
    130         addedge(u, v, w);  
    131     }
    132 }
    133 
    134 int main(){
    135     while(~scanf("%d%d",&m,&n)){
    136         pre_init();
    137         mapping();
    138         int s,t;
    139         s = 1;t = n;
    140         int ans = SAP(s,t);
    141         printf("%d
    ",ans);
    142     }
    143     return 0;
    144 }
  • 相关阅读:
    PAT 解题报告 1009. Product of Polynomials (25)
    PAT 解题报告 1007. Maximum Subsequence Sum (25)
    PAT 解题报告 1003. Emergency (25)
    PAT 解题报告 1004. Counting Leaves (30)
    【转】DataSource高级应用
    tomcat下jndi配置
    java中DriverManager跟DataSource获取getConnection有什么不同?
    理解JDBC和JNDI
    JDBC
    Dive into python 实例学python (2) —— 自省,apihelper
  • 原文地址:https://www.cnblogs.com/Asumi/p/9751117.html
Copyright © 2011-2022 走看看