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
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值