#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;
}
Dinic算法路径输出
最新推荐文章于 2024-06-06 21:15:00 发布