最小费用最大流入门

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\n", 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\n",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\n");
112             continue;
113         }
114         printf("SUBOPTIMAL\n");
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\n" ,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

 

posted @ 2015-07-27 11:21  UsedRose  阅读(210)  评论(0编辑  收藏  举报