最大流
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
const int N = 1100;
const int INF = 0x3f3f3f3f;
struct Node
{
int to;//终点
int cap; //容量
int rev; //反向边
};
vector<Node> v[N];
bool used[N];
void add_Node(int from,int to,int cap) //重边情况不影响
{
v[from].push_back((Node){to,cap,v[to].size()});
v[to].push_back((Node){from,0,v[from].size()-1});
}
int dfs(int s,int t,int f)
{
if(s==t)
return f;
used[s]=true;
for(int i=0;i<v[s].size();i++)
{
Node &tmp = v[s][i]; //注意
if(used[tmp.to]==false && tmp.cap>0)
{
int d=dfs(tmp.to,t,min(f,tmp.cap));
if(d>0)
{
tmp.cap-=d;
v[tmp.to][tmp.rev].cap+=d;
return d;
}
}
}
return 0;
}
int max_flow(int s,int t)
{
int flow=0;
for(;;){
memset(used,false,sizeof(used));
int f=dfs(s,t,INF);
if(f==0)
return flow;
flow+=f;
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
memset(v,0,sizeof(v));
for(int i=0;i<n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add_Node(x,y,z);
}
printf("%d\n",max_flow(1,m));
}
}
最小费用最大流(华为杯)
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
#include<functional>
#include<windows.h>
using namespace std;
#define INF 100000
struct Node
{
int to;//终点
int cap;//容量
int flow=0;
int rev; //反向点
int cost; //费用
};
typedef vector<Node>* Graph;
void add_Node(Graph v,int from, int to, int cap,int cost) //加边
{
Node nodefrom,nodeto;
nodefrom.to = to, nodefrom.cap =cap,nodefrom.rev = v[to].size(),nodefrom.cost = cost;
v[from].push_back(nodefrom);
nodeto.to = from, nodeto.cap =cap, nodeto.rev = v[from].size()-1,nodeto.cost =cost;
v[to].push_back(nodeto);
}
bool judgesign(int n)
{
if (n >= 0)
return 1;
else
return -1;
}//判断符号
bool SPFA(Graph v, int n,int s, int t, int &flow, int &cost)
{
int *inq=new int [n];//是否在队列中
int *d=new int[n];//距离
int *p = new int[n];//上一条弧
int *q = new int[n];
int *a = new int[n];//可改进量
for (int i = 0; i<n; i++)
d[i] = INF,inq[i]=0;
d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
queue<int> Q;
Q.push(s);
while (!Q.empty())
{
int u = Q.front();
for (int i = 0; i<v[u].size(); i++)
{
Node& e = v[u][i];
if (abs(e.cap) >abs(e.flow)&& d[e.to]>d[u]+e.cost*judgesign(e.flow))//满足可增广且可变短
{
d[e.to] = d[u] + e.cost*judgesign(e.flow);
p[e.to] = u;
q[e.to] = i;
if (judgesign(e.flow))
a[e.to] = min(a[u],e.cap-e.flow);
else
a[e.to] = min(a[u],abs(e.flow));
if (!inq[e.to])
{
inq[e.to]++;
Q.push(e.to);
}
}
}
Q.pop();
inq[u]--;
}
if (d[t] == INF) return false;//汇点不可达则退出
flow += a[t];
cost += d[t] * a[t];
int tmp= t;
while (tmp != s)//更新正向边和反向边
{
v[p[tmp]][q[tmp]].flow+= a[t];
v[tmp][v[p[tmp]][q[tmp]].rev].flow -= a[t];
tmp = p[tmp];
}
return true;
}//spfa找增广路径
pair<int,int> MincotMaxflow(Graph v,int n,int s, int t)
{
int flow = 0,cost = 0;
while (SPFA(v,n,s, t, flow, cost)) ;
return make_pair(flow,cost);
}//最小费用最大流
int dfs(Graph v, int s, int superdst, int flow,int *use)
{
if (s==superdst)
return flow;
use[s] = true;
for (int i = 0; i < v[s].size(); i++)
{
if (v[s][i].flow&&use[v[s][i].to]==false)
{
cout << s << ends;
int d = dfs(v,v[s][i].to, superdst,min(flow, v[s][i].flow),use);
if (d>0)
{
v[s][i].flow -= d;
v[v[s][i].to][v[s][i].rev].flow += d;
return d;
}
}
}
return 0;
}深搜打印路径
void PrintPath(Graph v, int n,int supersrc, int superdst)
{
int flow;
int *use = new int[n];
for (int i = 0; i < n; i++)
use[i] = false;
use[supersrc] = true;
flow = INF;
for (int i=0; i < v[supersrc].size();i++)
{
while (flow = dfs(v, v[supersrc][i].to, superdst, flow, use))
{
for (int i = 0; i < n-1; i++)
use[i] = false;
cout << flow << endl;
flow = INF;
};
for (int i = 0; i < n-1; i++)
use[i] = false;
flow = INF;
}
}//路径打印
int cmp(const void *a, const void *b)
{
return (*(pair<int, int> *)b).second - (*(pair<int, int> *)a).second;
}
void print(Graph v, int n)
{
for (int i = 0; i < n; i++)
{
cout << i << endl;
for (int j = 0; j < v[i].size(); j++)
{
cout << v[i][j].to << ":" << v[i][j].flow<<ends<<v[i][j].cap<<ends;
}
cout << endl;
}
}//打印图 调试用的
void FindServer(Graph v,int n,int request,int servercost)
{
vector<Node> *copy = new vector<Node>[n];
for (int i = 0; i < n-1; i++)
copy[i].assign(v[i].begin(), v[i].end());
pair<int, int> *a = new pair<int, int>[n-2];
for (int i = 0; i < n - 2; i++)
{
a[i].first = i;
for (int j = 0; j < v[i].size(); j++)
a[i].second += v[i][j].cap;
}
qsort(a, n - 2, sizeof(pair<int,int>), cmp);
int sum=0;
int count=0;
pair<int,int> result;
for (count = 0; count < n - 2; count++)
{
sum += a[count].second;
if (sum>request)
break;
}
for(int i=0;i<=count;i++)
add_Node(copy,n - 1,a[i].first,INF,0);
result =MincotMaxflow(copy, n, n - 1, n - 2);
while (result.first != request)
{
for (int i = 0; i < n; i++)
copy[i].assign(v[i].begin(), v[i].end());
count += 1;
for (int i = 0; i <= count; i++)
add_Node(copy, n - 1, a[i].first, INF, 0);
result = MincotMaxflow(copy, n, n - 1, n - 2);
}
for (int i = 0; i < copy[n - 1].size();i++)
if (copy[n - 1][i].flow == 0)
copy[n - 1].erase(copy[n-1].begin()+i);
PrintPath(copy, n, n - 1, n - 2);
cout << "费用为" << servercost*copy[n - 1].size() + result.first << endl;
}
int main()
{
int webnum, roadnum, consumernum;
cin >> webnum >> roadnum >> consumernum;//输入 网络结点,链路,消费结点
int n = webnum + consumernum+2;
Graph v = new vector<Node>[n];
int servercost,from,to,cost,cap;
cin >> servercost;
for (int i = 0; i < roadnum; i++)
{
cin >> from >> to >> cap >> cost;
add_Node(v, from, to, cap, cost);//加边
}
int request=0;
for (int i = webnum; i < webnum+consumernum; i++)
{
cin >> to>>from >>cap;
request += cap;
to += webnum;
add_Node(v, from, to, cap, 0);
add_Node(v, to, n-2, cap, 0);
}//加边形成超级汇点
cout <<request<<endl;
FindServer(v, n, request,servercost);
system("pause");
}
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
#include<functional>
#include<windows.h>
using namespace std;
#define INF 100000
struct Node
{
int to;//终点
int cap;//容量
int flow=0;
int rev; //反向点
int cost; //费用
};
typedef vector<Node>* Graph;
void add_Node(Graph v,int from, int to, int cap,int cost) //加边
{
Node nodefrom,nodeto;
nodefrom.to = to, nodefrom.cap =cap,nodefrom.rev = v[to].size(),nodefrom.cost = cost;
v[from].push_back(nodefrom);
nodeto.to = from, nodeto.cap =cap, nodeto.rev = v[from].size()-1,nodeto.cost =cost;
v[to].push_back(nodeto);
}
bool judgesign(int n)
{
if (n >= 0)
return 1;
else
return -1;
}//判断符号
bool SPFA(Graph v, int n,int s, int t, int &flow, int &cost)
{
int *inq=new int [n];//是否在队列中
int *d=new int[n];//距离
int *p = new int[n];//上一条弧
int *q = new int[n];
int *a = new int[n];//可改进量
for (int i = 0; i<n; i++)
d[i] = INF,inq[i]=0;
d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
queue<int> Q;
Q.push(s);
while (!Q.empty())
{
int u = Q.front();
for (int i = 0; i<v[u].size(); i++)
{
Node& e = v[u][i];
if (abs(e.cap) >abs(e.flow)&& d[e.to]>d[u]+e.cost*judgesign(e.flow))//满足可增广且可变短
{
d[e.to] = d[u] + e.cost*judgesign(e.flow);
p[e.to] = u;
q[e.to] = i;
if (judgesign(e.flow))
a[e.to] = min(a[u],e.cap-e.flow);
else
a[e.to] = min(a[u],abs(e.flow));
if (!inq[e.to])
{
inq[e.to]++;
Q.push(e.to);
}
}
}
Q.pop();
inq[u]--;
}
if (d[t] == INF) return false;//汇点不可达则退出
flow += a[t];
cost += d[t] * a[t];
int tmp= t;
while (tmp != s)//更新正向边和反向边
{
v[p[tmp]][q[tmp]].flow+= a[t];
v[tmp][v[p[tmp]][q[tmp]].rev].flow -= a[t];
tmp = p[tmp];
}
return true;
}//spfa找增广路径
pair<int,int> MincotMaxflow(Graph v,int n,int s, int t)
{
int flow = 0,cost = 0;
while (SPFA(v,n,s, t, flow, cost)) ;
return make_pair(flow,cost);
}//最小费用最大流
int dfs(Graph v, int s, int superdst, int flow,int *use)
{
if (s==superdst)
return flow;
use[s] = true;
for (int i = 0; i < v[s].size(); i++)
{
if (v[s][i].flow&&use[v[s][i].to]==false)
{
cout << s << ends;
int d = dfs(v,v[s][i].to, superdst,min(flow, v[s][i].flow),use);
if (d>0)
{
v[s][i].flow -= d;
v[v[s][i].to][v[s][i].rev].flow += d;
return d;
}
}
}
return 0;
}深搜打印路径
void PrintPath(Graph v, int n,int supersrc, int superdst)
{
int flow;
int *use = new int[n];
for (int i = 0; i < n; i++)
use[i] = false;
use[supersrc] = true;
flow = INF;
for (int i=0; i < v[supersrc].size();i++)
{
while (flow = dfs(v, v[supersrc][i].to, superdst, flow, use))
{
for (int i = 0; i < n-1; i++)
use[i] = false;
cout << flow << endl;
flow = INF;
};
for (int i = 0; i < n-1; i++)
use[i] = false;
flow = INF;
}
}//路径打印
int cmp(const void *a, const void *b)
{
return (*(pair<int, int> *)b).second - (*(pair<int, int> *)a).second;
}
void print(Graph v, int n)
{
for (int i = 0; i < n; i++)
{
cout << i << endl;
for (int j = 0; j < v[i].size(); j++)
{
cout << v[i][j].to << ":" << v[i][j].flow<<ends<<v[i][j].cap<<ends;
}
cout << endl;
}
}//打印图 调试用的
void FindServer(Graph v,int n,int request,int servercost)
{
vector<Node> *copy = new vector<Node>[n];
for (int i = 0; i < n-1; i++)
copy[i].assign(v[i].begin(), v[i].end());
pair<int, int> *a = new pair<int, int>[n-2];
for (int i = 0; i < n - 2; i++)
{
a[i].first = i;
for (int j = 0; j < v[i].size(); j++)
a[i].second += v[i][j].cap;
}
qsort(a, n - 2, sizeof(pair<int,int>), cmp);
int sum=0;
int count=0;
pair<int,int> result;
for (count = 0; count < n - 2; count++)
{
sum += a[count].second;
if (sum>request)
break;
}
for(int i=0;i<=count;i++)
add_Node(copy,n - 1,a[i].first,INF,0);
result =MincotMaxflow(copy, n, n - 1, n - 2);
while (result.first != request)
{
for (int i = 0; i < n; i++)
copy[i].assign(v[i].begin(), v[i].end());
count += 1;
for (int i = 0; i <= count; i++)
add_Node(copy, n - 1, a[i].first, INF, 0);
result = MincotMaxflow(copy, n, n - 1, n - 2);
}
for (int i = 0; i < copy[n - 1].size();i++)
if (copy[n - 1][i].flow == 0)
copy[n - 1].erase(copy[n-1].begin()+i);
PrintPath(copy, n, n - 1, n - 2);
cout << "费用为" << servercost*copy[n - 1].size() + result.first << endl;
}
int main()
{
int webnum, roadnum, consumernum;
cin >> webnum >> roadnum >> consumernum;//输入 网络结点,链路,消费结点
int n = webnum + consumernum+2;
Graph v = new vector<Node>[n];
int servercost,from,to,cost,cap;
cin >> servercost;
for (int i = 0; i < roadnum; i++)
{
cin >> from >> to >> cap >> cost;
add_Node(v, from, to, cap, cost);//加边
}
int request=0;
for (int i = webnum; i < webnum+consumernum; i++)
{
cin >> to>>from >>cap;
request += cap;
to += webnum;
add_Node(v, from, to, cap, 0);
add_Node(v, to, n-2, cap, 0);
}//加边形成超级汇点
cout <<request<<endl;
FindServer(v, n, request,servercost);
system("pause");
}