图论-网络流

最大流

#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");
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值