zoukankan      html  css  js  c++  java
  • 最小费用最大流入门

    poj 3281

    学会建图啊。。 啊。。 啊。。

    S(0)-食物(2n+i)-牛1(i)-牛2(n+i)-饮料(2n+F+i)-T(2n+F+D+1)

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<set>
      7 #include<map>
      8 #include<stack>
      9 #include<vector>
     10 #include<queue>
     11 #include<string>
     12 #include<sstream>
     13 #define eps 1e-9
     14 #define ALL(x) x.begin(),x.end()
     15 #define INS(x) inserter(x,x.begin())
     16 #define FOR(i,j,k) for(int i=j;i<=k;i++)
     17 #define MAXN 1005
     18 #define MAXM 30005
     19 using namespace std;
     20 typedef long long LL;
     21 int i, j, k, n, m, x, y, T, ans, big, cas, F, D, S, f, d, id;
     22 bool flag;
     23 
     24 const int inf = 0x3f3f3f3f;
     25 struct edgenode
     26 {
     27     int from, to, next;
     28     int cap;
     29 }edge[MAXM];
     30 int Edge, head[MAXN], ps[MAXN], dep[MAXN];
     31 
     32 void add_edge(int x, int y, int c)
     33 {
     34     edge[Edge].from = x;
     35     edge[Edge].to = y;
     36     edge[Edge].cap = c;
     37     edge[Edge].next = head[x];
     38     head[x] = Edge++;
     39 
     40     edge[Edge].from = y;
     41     edge[Edge].to = x;
     42     edge[Edge].cap = 0;
     43     edge[Edge].next = head[y];
     44     head[y] = Edge++;
     45 }
     46 
     47 int dinic(int n, int s, int t)
     48 {
     49     int tr, flow = 0;
     50     int i, j, k, l, r, top;
     51     while (1){
     52         memset(dep, -1, (n + 1)*sizeof(int));
     53         for (l = dep[ps[0] = s] = 0, r = 1; l != r;)//BFS部分,将给定图分层
     54         {
     55             for (i = ps[l++], j = head[i]; j != -1; j = edge[j].next)
     56             {
     57                 if (edge[j].cap&&-1 == dep[k = edge[j].to])
     58                 {
     59                     dep[k] = dep[i] + 1; ps[r++] = k;
     60                     if (k == t)
     61                     {
     62                         l = r;
     63                         break;
     64                     }
     65                 }
     66             }
     67         }
     68         if (dep[t] == -1)break;
     69 
     70         for (i = s, top = 0;;)//DFS部分
     71         {
     72             if (i == t)//当前点就是汇点时
     73             {
     74                 for (k = 0, tr = inf; k<top; ++k)
     75                     if (edge[ps[k]].cap<tr)tr = edge[ps[l = k]].cap;
     76 
     77                 for (k = 0; k<top; ++k)
     78                     edge[ps[k]].cap -= tr, edge[ps[k] ^ 1].cap += tr;
     79 
     80                 flow += tr;
     81                 i = edge[ps[top = l]].from;
     82             }
     83 
     84             for (j = head[i]; j != -1; j = edge[j].next)//找当前点所指向的点
     85                 if (edge[j].cap&&dep[i] + 1 == dep[edge[j].to]) break;
     86 
     87             if (j != -1)
     88             {
     89                 ps[top++] = j;//当前点有所指向的点,把这个点加入栈中
     90                 i = edge[j].to;
     91             }
     92             else
     93             {
     94                 if (!top) break;//当前点没有指向的点,回溯
     95                 dep[i] = -1;
     96                 i = edge[ps[--top]].from;
     97             }
     98         }
     99     }
    100     return flow;
    101 }
    102 
    103 
    104 int main()
    105 {
    106     memset(head, -1, sizeof(head)); Edge = 0;
    107     scanf("%d%d%d", &n, &F, &D);
    108     S = 0;
    109     T = n + n + F + D + 1;
    110     for (i = 1; i <= F; i++)
    111     {
    112         add_edge(S, 2 * n + i, 1);
    113     }
    114     for (i = 1; i <= D; i++)
    115     {
    116         add_edge(2 * n + F + i, T, 1);
    117     }
    118 
    119     for (i = 1; i <= n; i++)
    120     {
    121         scanf("%d%d", &f, &d);
    122         add_edge(i, n + i, 1);
    123         for (j = 1; j <= f; j++)
    124         {
    125             scanf("%d", &id);
    126             id = 2 * n + id;
    127             add_edge(id, i, 1);
    128         }
    129         for (j = 1; j <= d; j++)
    130         {
    131             scanf("%d", &id);
    132             id = 2 * n + F + id;
    133             add_edge(n + i, id, 1);
    134         }
    135     }
    136     printf("%d
    ", dinic(T + 1, S, T));
    137     return 0;
    138 }
    View Code

    poj 3469

    将每个任务规约为一个点,添加源汇点s.t,s和每个任务相连,边权为任务在s上处理用的时间;
    每个任务和t相连,边权为任务在t上处理用的时间.对于(a,b,w),连两条边(a,b,w)和(b,a,w);
    为什么最小割就是解呢?
    由最小割的定义,点基被分成两部分S.T,S为源点能到达的点的集合,其余点构成T;
    再来看此题,假如s和a之间的边是割,那么a在s上被处理,否则a在t上被处理,s能到达的点在t上处理,其余点在t上处理;

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <queue>
     5 #define M 6050000
     6 #define N 20200
     7 #define inf 0x3f3f3f3f
     8 using namespace std;
     9 
    10 
    11 struct node {
    12   int v,w,next;
    13 } edge[M];
    14 int head[N],cnt,l[N],n,m,s,t;
    15 void add(int u,int v,int w) {
    16   edge[cnt].v=v;
    17   edge[cnt].w=w;
    18   edge[cnt].next=head[u];
    19   head[u]=cnt++;
    20 
    21   edge[cnt].v=u;
    22   edge[cnt].w=0;
    23   edge[cnt].next=head[v];
    24   head[v]=cnt++;
    25 }
    26 void add2(int u,int v,int w) {
    27   edge[cnt].v=v;
    28   edge[cnt].w=w;
    29   edge[cnt].next=head[u];
    30   head[u]=cnt++;
    31 
    32   edge[cnt].v=u;
    33   edge[cnt].w=w;
    34   edge[cnt].next=head[v];
    35   head[v]=cnt++;
    36 }
    37 int bfs() {
    38   memset(l,-1,sizeof(l));
    39   l[s]=0;
    40   int i,u,v;
    41   queue<int >Q;
    42   Q.push(s);
    43   while(!Q.empty()) {
    44     u=Q.front();
    45     Q.pop();
    46     for(i=head[u]; i!=-1; i=edge[i].next) {
    47       v=edge[i].v;
    48       if(l[v]==-1&&edge[i].w) {
    49         l[v]=l[u]+1;
    50         Q.push(v);
    51       }
    52     }
    53   }
    54   return l[t]>0;
    55 }
    56 int dfs(int u,int f) {
    57   int a,flow=0;
    58   if(u==t)return f;
    59   for(int i=head[u]; i!=-1; i=edge[i].next) {
    60     int v=edge[i].v;
    61     if(l[v]==l[u]+1&&edge[i].w&&(a=dfs(v,min(f,edge[i].w)))) {
    62       edge[i].w-=a;
    63       edge[i^1].w+=a;
    64       flow+=a;//多路增广
    65       f-=a;
    66       if(!f)break;
    67     }
    68   }
    69   if(!flow)l[u]=-1;//当前弧优化
    70   return flow;
    71 }
    72 int dinic() {
    73   int a,ans=0;
    74   while(bfs())
    75     while(a=dfs(s,inf))
    76       ans+=a;
    77   return ans;
    78 }
    79 
    80 int main() {
    81   int i,j,u,v,w;
    82   while(~scanf("%d%d",&n,&m)) {
    83     memset(head,-1,sizeof(head));
    84     cnt=0;
    85     s=0;
    86     t=n+1;
    87     for(i=1; i<=n; i++) {
    88       scanf("%d%d",&u,&v);
    89       add(s,i,u);
    90       add(i,t,v);
    91     }
    92     for(i=1; i<=m; i++) {
    93       scanf("%d%d%d",&u,&v,&w);
    94       add2(u,v,w);
    95     }
    96     printf("%d
    ",dinic());
    97   }
    98 }
    View Code

     poj 2175

    消圈判断费用流是否最优

    请看http://m.blog.csdn.net/blog/u013761036/46363631

     大牛代码:

      1 #include<queue>
      2 #include<stdio.h>
      3 #include<string.h>
      4 
      5 #define N_node 205
      6 #define N_edge 30000
      7 #define INF 100000000
      8 
      9 using namespace std;
     10 
     11 typedef struct
     12 {
     13     int from ,to ,cost ,flow ,next;
     14 }STAR;
     15 
     16 typedef struct
     17 {
     18     int a ,b ,c;
     19 }NODE;
     20 
     21 STAR E[N_edge];
     22 int list[N_node] ,tot;
     23 int C[N_node];//入队次数
     24 int mer[N_node];//记录路径
     25 int s_x[N_node] ,mark[N_node];
     26 int now[N_node][N_node];
     27 NODE A[N_node] ,B[N_node];
     28 
     29 void add(int a ,int b ,int c ,int d)
     30 {
     31     E[++tot].from = a;
     32     E[tot].to = b;
     33     E[tot].cost = c;
     34     E[tot].flow = d;
     35     E[tot].next = list[a];
     36     list[a] = tot;
     37 }
     38 
     39 int abss(int x)
     40 {
     41     return x > 0 ? x : -x;
     42 }
     43 
     44 bool Spfa(int s ,int n)
     45 {
     46     for(int i = 0 ;i <= n ;i ++)
     47     s_x[i] = INF;
     48     memset(mark ,0 ,sizeof(mark));
     49     memset(C ,0 ,sizeof(C));
     50     queue<int>q; q.push(s);
     51     mark[s] = C[s] = 1 ,s_x[s] = 0;
     52     int xin ,tou;
     53     memset(mer ,255 ,sizeof(mer));
     54     while(!q.empty())
     55     {
     56         tou = q.front();
     57         q.pop();
     58         mark[tou] = 0;
     59         for(int k = list[tou] ;k ;k = E[k].next)
     60         {
     61             xin = E[k].to;
     62             if(s_x[xin] > s_x[tou] + E[k].cost && E[k].flow)
     63             {
     64                 s_x[xin] = s_x[tou] + E[k].cost;
     65                 mer[xin] = k;
     66                 if(!mark[xin])
     67                 {
     68                     mark[xin] = 1;
     69                     q.push(xin);
     70                     if(++C[xin] > n) return xin;
     71                 }
     72             }
     73         }
     74     }
     75     return 0;
     76 }
     77 
     78 int main ()
     79 {
     80     int n ,m ,i ,j;
     81     int st[N_node];
     82     while(~scanf("%d %d" ,&n ,&m))
     83     {
     84         for(i = 1 ;i <= n ;i++)
     85         scanf("%d %d %d" ,&A[i].a ,&A[i].b ,&A[i].c);
     86         for(i = 1 ;i <= m ;i ++)
     87         scanf("%d %d %d" ,&B[i].a ,&B[i].b ,&B[i].c);
     88         memset(st ,0 ,sizeof(st));
     89         for(i = 1 ;i <= n ;i ++)
     90         for(j = 1 ;j <= m ;j ++)
     91         {
     92             scanf("%d" ,&now[i][j]);
     93             st[j] += now[i][j];
     94         }
     95         memset(list ,0 ,sizeof(list));
     96         tot = 1;
     97         int ss = 0 ,tt = n + m + 1;
     98         for(i = 1 ;i <= n ;i ++)
     99         add(ss ,i ,0 ,0),add(i ,ss ,0 ,A[i].c);
    100         for(i = 1 ;i <= m ;i ++)
    101         add(i + n ,tt ,0 ,B[i].c - st[i]) ,add(tt ,i + n ,0 ,st[i]);
    102         for(i = 1 ;i <= n ;i ++)
    103         for(j = 1 ;j <= m ;j ++)
    104         {
    105             add(i ,j + n ,abss(A[i].a-B[j].a)+abss(A[i].b - B[j].b) + 1 ,INF - now[i][j]);
    106             add(j + n ,i ,-(abss(A[i].a-B[j].a)+abss(A[i].b - B[j].b) + 1) ,now[i][j]);
    107         }
    108         int x = Spfa(tt ,tt);
    109         if(!x)
    110         {
    111             printf("OPTIMAL
    ");
    112             continue;
    113         }
    114         printf("SUBOPTIMAL
    ");
    115         memset(mark ,0 ,sizeof(mark));
    116         i = mer[x];
    117         while(1)//找到一个肯定在环上的点
    118         {
    119             x = E[i].to;
    120             if(mark[x]) break;
    121             mark[x] = 1;
    122             i = mer[E[i].from];
    123         }
    124         memset(mark ,0 ,sizeof(mark));
    125         for(i = mer[x] ;i + 1 ;i = mer[E[i].from])
    126         {
    127             int a = E[i].from ,b = E[i].to;
    128             if(a >= 1 && a <= n && b >= n + 1 && b <= n + m)
    129             now[a][b-n] ++;
    130             if(a >= n + 1 && a <= n + m && b >= 1 && b <= n)
    131             now[b][a-n] --;
    132             if(mark[a] && mark[b]) break;
    133             mark[a] = mark[b] = 1;
    134         }
    135         for(i = 1 ;i <= n ;i ++)
    136         for(j = 1 ;j <= m ;j ++)
    137         if(j == m) printf("%d
    " ,now[i][j]);
    138         else printf("%d " ,now[i][j]);
    139     }
    140     return 0;
    141 
    142 }
    View Code

    poj 2135

    对流量有要求的最小费用最大流

      1 /*Author :usedrose  */
      2 /*Created Time :2015/7/27 15:20:54*/
      3 /*File Name :2.cpp*/
      4 #include <cstdio>
      5 #include <iostream>
      6 #include <algorithm>
      7 #include <sstream>
      8 #include <cstdlib>
      9 #include <cstring>
     10 #include <climits>
     11 #include <vector>
     12 #include <string>
     13 #include <ctime>
     14 #include <cmath>
     15 #include <deque>
     16 #include <queue>
     17 #include <stack>
     18 #include <set>
     19 #include <map>
     20 #define INF 0x3f3f3f3f
     21 #define eps 1e-8
     22 #define pi acos(-1.0)
     23 #define MAXN 2010
     24 #define OK cout << "ok" << endl;
     25 #define o(a) cout << #a << " = " << a << endl
     26 #define o1(a,b) cout << #a << " = " << a << "  " << #b << " = " << b << endl
     27 using namespace std;
     28 typedef long long LL;
     29 
     30 struct edge {
     31     int to, cap, cost, rev;
     32 };
     33 
     34 int V;
     35 vector<edge> G[MAXN];
     36 int dist[MAXN];
     37 int prevv[MAXN], preve[MAXN];
     38 
     39 void add_edge(int from, int to, int cap, int cost)
     40 {
     41     G[from].push_back({ to, cap, cost, G[to].size() });
     42     G[to].push_back({ from, 0, -cost, G[from].size() - 1 });
     43 }
     44 
     45 //求解从s到t流量为f的最小费用流
     46 //不能增广返回-1
     47 int min_cost_flow(int s, int t, int f)
     48 {
     49     int res = 0;
     50     while (f > 0) {
     51         fill(dist, dist + V, INF);
     52         dist[s] = 0;
     53         bool update = true;
     54         while (update) {
     55             update = false;
     56             for (int v = 0; v < V; ++v) {
     57                 if (dist[v] == INF) continue;
     58                 for (int i = 0; i < G[v].size(); ++i) {
     59                     edge &e = G[v][i];
     60                     if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
     61                         dist[e.to] = dist[v] + e.cost;
     62                         prevv[e.to] = v;
     63                         preve[e.to] = i;
     64                         update = true;
     65                     }
     66                 }
     67             }
     68         }
     69 
     70         
     71         if (dist[t] == INF) return -1;
     72 
     73         int d = f;
     74         for (int v = t; v != s; v = prevv[v]) {
     75             d = min(d, G[prevv[v]][preve[v]].cap);
     76         }
     77         f -= d;
     78         res += d*dist[t];
     79         for (int v = t; v != s; v = prevv[v]) {
     80             edge &e = G[prevv[v]][preve[v]];
     81             e.cap -= d;
     82             G[v][e.rev].cap += d;
     83         }
     84     }
     85     return res;
     86 }
     87 
     88 void solve()
     89 {
     90     int x, y, w, m;
     91     cin >> V >> m;
     92     int s = 0, t = V - 1;
     93     for (int i = 0; i < m; ++i) {
     94         cin >> x >> y >> w;
     95         x--, y--;
     96         add_edge(x, y, 1, w);
     97         add_edge(y, x, 1, w);
     98     }
     99     cout << min_cost_flow(s, t, 2) << endl;
    100 }
    101 
    102 int main()
    103 {
    104     //freopen("data.in","r",stdin);
    105     //freopen("data.out","w",stdout);
    106     cin.tie(0);
    107     ios::sync_with_stdio(false);
    108     solve();
    109     return 0;
    110 }
    View Code
  • 相关阅读:
    Django forms组件
    Django 分页器
    Django Ajax
    Django 多表操作2
    js12种应该注意的地方
    Web自动化测试python环境中安装 --selenium安装、火狐和火狐驱动版本、谷歌和谷歌驱动版本、测试
    python学习-文件操作
    关于redis搭建环境
    扩展知识
    javascript之Banner图片焦点轮播
  • 原文地址:https://www.cnblogs.com/usedrosee/p/4679654.html
Copyright © 2011-2022 走看看