Dinic算法路径输出

#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <unordered_map>
#include <algorithm>
#include <array>
#include <queue>
#include <tuple>
#include <set>
#include <unordered_set>
#include <bitset>
#include <list>
#include <iomanip>
using namespace std;

class FNVHash {
	private:
		using ull = unsigned long long;
		static constexpr ull offset = 14695981039346656037ULL , prime = 1099511628211ULL;
		map<ull , string> Map;
	public:
		FNVHash() {}
		ull GetHash(const string &t) {
			ull hash = offset;
			for(auto it : t) {
				hash = (hash ^ it) * prime;
			}
			hash += hash << 13;
			hash ^= hash >> 7;
			hash += hash << 3;
			hash ^= hash >> 17;
			hash += hash << 5;
			return hash;
		}
		ull insert(const string &t) {
			ull hash = GetHash(t);
			if(Map.count(hash)) 
				return hash;
			Map[hash] = t;
			return hash;
		}
		bool erase(const string &t) {
			ull hash = GetHash(t);
			if(!Map.count(hash)) 
				return false;
			Map.erase(hash);
			return true;
		}
		string& GetString(ull Hash) {
			return Map[Hash];
		}
		bool IsExist(ull t) {
			return Map.count(t);
		}
		bool operator [] (const string &t) {
			return Map.count(GetHash(t));
		}
		bool operator [] (ull t) {
			return IsExist(t);
		}
};

namespace Mapping {
	using ull = unsigned long long;
	FNVHash Hash;
	unordered_map<int , ull> mapping;
	unordered_map<ull , int> mapping2;
	size_t NodeNumber = 0;
	void AddNode(const string &a ,const string &b , ull &s , ull &t) {
		if(!Hash[s]){
			Hash.insert(a);
			mapping[++NodeNumber] = s;
			mapping2[s] = NodeNumber;
		}
		if(!Hash[t]) {
			Hash.insert(b);
			mapping[++NodeNumber] = t;
			mapping2[t] = NodeNumber;
		}
		s = mapping2[s] , t = mapping2[t];		
	}
}

using namespace Mapping;

template<typename T>
class Graph {
	private:
		using Pos = int;
		using ull = unsigned long long;
		struct node {
			size_t to;
			Pos next;
			T value , origin;
			node() : next(End) {}
			node(size_t a , Pos b , T c , T d) : to(a) , next(b) , value(c) , origin(d) {};
		};
		vector<node> G;
		vector<Pos> head;
		vector<bool> vis , vis2;
		size_t k , EdgeNumber;
	public:
		static constexpr Pos End = 0;
		Graph(size_t n , size_t m) : head(n + 1 , End) , G(2) , k(2) , EdgeNumber(m) ,vis(n + 1) , vis2(n + 1) {
			G.reserve(m * 2 + 2);
		}
		size_t GetNodeNumber() {
			return head.size() - 1;
		}
		
		void BuildGraph() {
			for(int i = 0 ; i < EdgeNumber ; ++i) {
				string a , b;
				double v;
				cin >> a >> b >> v;
				ull s = Hash.GetHash(a), t = Hash.GetHash(b);
				AddNode(a , b , s , t);
				AddEdge(s , t , v);
				AddEdge(t , s , 0);
			}
		}
		void AddEdge(size_t s , size_t t , T v) {
			G.push_back({t , head[s] , v , v});
			head[s] = k;
			++k;
		}
		Pos NextEdge(size_t Pos) {
			return G[Pos].next;
		}
		T& GetValue(size_t Pos) {
			return G[Pos].value;
		}
		T& GetOriginValue(size_t Pos) {
			return G[Pos].origin;
		}
		Pos GetHead(size_t Pos) {
			return head[Pos];
		}
		Pos FlipEdge(size_t Pos) {
			return Pos ^ 1;
		}
		size_t GetCurrentNode(size_t Pos) {
			return G[Pos].to;
		}
		const vector<Pos>& GetHeadArray() {
			return head;
		}
		void pre(int s , int t) {
			queue<int> que;
			que.push(s);
			vis2[s] = true;
			while(!que.empty()) {
				int x = que.front();
				que.pop();
				for(int i = GetHead(x) ; i != End ; i = NextEdge(i)) {
					int to = GetCurrentNode(i);
					if(GetOriginValue(i) != 0) GetOriginValue(i) -= GetValue(i),
					GetValue(i) = 0;
					if(vis2[to]) continue;
					vis2[to] = true;
					que.push(to);
				}
			}
		}
		void DFS(int now , int t , double value , list<int> &&path) {
			if(value == 0) return;
			vis[now] = true;
			path.push_back(now);
			if(now == t) {
				vis[t] = false;
				for(auto it = path.begin() ; it != path.end() ; ++it) {
					if(it != --path.end())
						cout << Hash.GetString(mapping[*it]) << "->";
					else 
						cout << Hash.GetString(mapping[*it]) << " ";
				}
				cout << fixed << setw(2) << "Flow is :" << value <<'\n';
				path.pop_back();
				return;
			}
			double resi = value;
			for(int i = GetHead(now) ; i != End ; i = NextEdge(i)) {
				int to = GetCurrentNode(i);
				double v = GetOriginValue(i);
				if(vis[to] || resi == 0) continue;
				double tt = min(resi , GetOriginValue(i)); 
				DFS(to , t , tt ,  move(path));
				GetOriginValue(i) -= tt;
				resi -= tt;
			}
			path.pop_back();
			vis[now] = false;
			return;
		}
};

class DinicFlow {
	private:
		Graph<double> G;
		vector<int> Current , d;
		ull s , t;
	public:
		DinicFlow(int n , int m , string a , string b) : G(n , m) , d(n + 1) {
			s = Hash.GetHash(a) , t = Hash.GetHash(b);
			AddNode(a , b , s , t);
		}
		bool BFS() {
			Current = G.GetHeadArray();
			fill(d.begin() , d.end() , 0);
			d[s] = 1;
			queue<int> que;
			que.push(s);
			while(!que.empty()) {
				int front = que.front();
				que.pop();
				for(int i = G.GetHead(front) ; i != G.End ; i = G.NextEdge(i)) {
					int Node = G.GetCurrentNode(i);
					if(G.GetValue(i) > 0 && d[Node] == 0) {
						d[Node] = d[front] + 1;
						que.push(Node);
					}
				}
			}
			return d[t] != 0;
		}
		double DFS(int now , double MaxFlow) {
			if(now == t) 
				return MaxFlow;
			double sum = 0;
			for(int i = Current[now] ; i != G.End ; i = G.NextEdge(i)) {
				Current[now] = i; 
				int Node = G.GetCurrentNode(i);
				if(G.GetValue(i) > 0 && d[Node] == d[now] + 1) {
					double f = DFS(Node ,min(MaxFlow , static_cast<double>(G.GetValue(i))));
					G.GetValue(i) -= f;
					G.GetValue(G.FlipEdge(i)) += f;
					sum += f;
					MaxFlow -= f;
					if(MaxFlow == 0) break;
				}
			}
			if(sum == 0)
				Current[now] = 0;
			return sum;
		}
		double Main() {
			constexpr double Infinity = 1e12;
			double ans = 0;
			G.BuildGraph();
			while(BFS()) {
				Current = G.GetHeadArray();
				ans += DFS(s , Infinity);
			}
			G.pre(s , t);
			G.DFS(s , t , Infinity , list<int>{});	
			return ans;
		}
};
void solve() {
	int n , m;
	string s , t;
	cin >> n >> m >> s >> t;
	DinicFlow Solve(n , m , s , t);
	double ans = Solve.Main();
	cout << fixed << "Sum of Flow is : " << ans << '\n';
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	clog << "请输入当前目录下的文件" << endl;
	string path;
	cin >> path;
	freopen(path.data() , "r" , stdin);
	freopen((path.erase(path.rfind(".") , path.size()) + "的输出.out").data() , "w" , stdout);
	solve();	
	clog << "处理完成" << endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Dinic算法是一种用来解决最大流问题的算法,它的核心思想是构建分层图和阻塞流量的概念。通过多次增广路径的查找来找出最大流。 在Python中实现Dinic算法可以参考以下步骤: 1. 首先,需要定义一个图的类,包括节点数和邻接表等属性,用来存储图的结构。 2. 实现图的构建函数,根据边的信息添加邻接表。 3. 基于Dinic算法,需要实现一个辅助函数来在网络中查找增广路径。可以使用广度优先搜索(BFS)或深度优先搜索(DFS)来实现。通过不断搜索增广路径,直到找不到增广路径为止。 4. 实现Dinic算法的主函数,其中包括初始化流量和残余网络,以及进行多次增广路径搜索的过程。 5. 在每一次增广路径搜索中,需要更新流量和残余网络,并计算每一条边的容量。 6. 最后,需要输出最大流的值。 以下是一种可能的实现方式: ```python class Graph: def __init__(self, nodes): self.nodes = nodes self.adjacency = [[] for _ in range(nodes)] def add_edge(self, u, v, capacity): self.adjacency[u].append([v, capacity, 0, len(self.adjacency[v])]) self.adjacency[v].append([u, 0, 0, len(self.adjacency[u]) - 1]) def bfs(self, start, end): # 使用BFS查找增广路径 level = [-1] * self.nodes level[start] = 0 queue = [start] while queue: current_node = queue.pop(0) for neighbor in self.adjacency[current_node]: if level[neighbor[0]] < 0 and neighbor[1] > neighbor[2]: # 更新节点的层级 level[neighbor[0]] = level[current_node] + 1 queue.append(neighbor[0]) return level[end] >= 0 def dfs(self, current_node, end, flow): # 使用DFS查找增广路径 if current_node == end: return flow while self.adjacency[current_node][current_edge[current_node]][1] <= self.adjacency[current_node][current_edge[current_node]][2]: current_edge[current_node] += 1 for i in range(current_edge[current_node], len(self.adjacency[current_node])): neighbor = self.adjacency[current_node][i] if level[neighbor[0]] == level[current_node] + 1 and neighbor[1] > neighbor[2]: min_flow = min(flow, neighbor[1] - neighbor[2]) temp_flow = self.dfs(neighbor[0], end, min_flow) if temp_flow > 0: neighbor[2] += temp_flow self.adjacency[neighbor[0]][neighbor[3]][2] -= temp_flow return temp_flow return 0 def dinic(self, start, end): level = [0] * self.nodes max_flow = 0 while self.bfs(start, end): current_edge = [0] * self.nodes while True: flow = self.dfs(start, end, float('inf')) if not flow: break max_flow += flow return max_flow g = Graph(4) g.add_edge(0, 1, 3) g.add_edge(0, 2, 2) g.add_edge(1, 2, 2) g.add_edge(1, 3, 1) g.add_edge(2, 3, 3) print("最大流为:", g.dinic(0, 3)) ``` 这个实现中,以一个简单的图作为例子进行了测试。首先,创建一个有4个节点的图,然后添加边和容量。最后,通过调用dinic函数来计算最大流的值,并将结果输出。 希望以上回答对你有所帮助,如果有任何问题需要进一步解答,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值