Cod sursa(job #3302558)

Utilizator Ilie_MityIlie Dumitru Ilie_Mity Data 8 iulie 2025 20:06:29
Problema Traseu Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.18 kb
// Ilie "The-Winner" Dumitru
// Dumnezeu sa o ierte
#include<bits/stdc++.h>
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using ll=long long;
constexpr int NMAX=64;
constexpr ll MOD=1000000009;

template<class T> constexpr T INF() {return std::numeric_limits<T>::max()/4;};
template<class F, class C>
struct MFMC {
	struct Edge { int to, rev; F cap, flow; C cost; };

	int n;
	std::vector<std::vector<Edge> > graph;
	std::vector<int> par;
	std::vector<C> dist;
	std::vector<C> pi;
	std::vector<Edge> es;

	MFMC(int n) : n(n), graph(n), par(n), dist(n), pi(n) {}

	void AddEdge(int a, int b, F cap, C cost, F flow = 0) {
		graph[a].push_back({b, sz(graph[b]), cap, flow, cost});
		graph[b].push_back({a, sz(graph[a])-1, 0, -flow, -cost});
	}
	bool relax(int from, const Edge& e) {
		if (dist[from] == INF<C>()) return false;
		auto now = dist[from] + pi[from] - pi[e.to] + e.cost;
		if (e.flow < e.cap && now < dist[e.to])
			return dist[e.to] = now, par[e.to] = e.rev, true;
		return false;
	}
	bool dijkstra(int s, int t) {
		std::priority_queue<std::pair<C, int> > pq;

		dist.assign(n, INF<C>()); par.assign(n, -1);
		dist[s] = 0; pq.emplace(0, s);
		while (!pq.empty()) {
			auto [d, node] = pq.top(); pq.pop();
			if (dist[node] != -d) continue;
			for (auto& e : graph[node])
				if (relax(node, e))
					pq.emplace(-dist[e.to], e.to);
		}
		for (int i = 0; i < n; ++i)
			pi[i] = std::min(pi[i] + dist[i], INF<C>());
		return par[t] != -1;
	}
	std::pair<F, C> Compute(int s, int t) {
		F flow = 0; C cost = 0;
		while (dijkstra(s, t)) {
			F now = INF<F>();
			for (int phase : {0, 1}) {
				for (int node = t; node != s; ) {
					auto& e1 = graph[node][par[node]];
					auto& e2 = graph[e1.to][e1.rev];
					if (!phase) now = std::min(now, e2.cap - e2.flow);
					else e2.flow += now, e1.flow -= now;
					node = e1.to;
				}
			}
			flow += now;
			cost += pi[t]*now;
		}
		return {flow, cost};
	}
	// If some costs can be negative, call this before maxflow:
	void SetPi(int s) { // (otherwise, leave this out)
		dist.assign(n, INF<C>()); dist[s] = 0;
		int it = n, ch = 1;
		while (ch-- && it--)
			for (int i = 0; i < n; ++i)
				for (auto& e : graph[i])
					ch |= relax(i, e);
		assert(it >= 0); // negative cost cycle
		pi = dist;
	}
};

int N, M;
int G[NMAX][NMAX];
int H[NMAX][NMAX];

int main()
{
	FILE* f=fopen("traseu.in", "r"), *g=fopen("traseu.out", "w");
	int i, j, k, a, b, c, tot=0, in, out;

	fscanf(f, "%d%d", &N, &M);
	for(i=0;i<N;++i)
		for(j=0;j<N;++j)
		{
			H[i][j]=(i!=j)*INF<int>();
			G[i][j]=INF<int>();
		}
	for(i=0;i<M;++i)
	{
		fscanf(f, "%d%d%d", &a, &b, &c);
		--a;
		--b;
		G[a][b]=H[a][b]=c;
		tot+=c;
	}

	for(k=0;k<N;++k)
		for(i=0;i<N;++i)
			for(j=0;j<N;++j)
				H[i][j]=std::min(H[i][j], H[i][k]+H[k][j]);

	MFMC<int, int> F(N*2+2);
	for(i=0;i<N;++i)
	{
		in=out=0;
		for(j=0;j<N;++j)
		{
			in+=(G[j][i]<INF<int>());
			out+=(G[i][j]<INF<int>());
		}

		if(in>out)
			F.AddEdge(N*2, i, in-out, 0);
		else if(in<out)
			F.AddEdge(i+N, N*2+1, out-in, 0);
	}

	for(i=0;i<N;++i)
		for(j=0;j<N;++j)
			if(H[i][j]>0 && H[i][j]<INF<int>())
				F.AddEdge(i, N+j, NMAX, H[i][j]);

	auto p=F.Compute(N*2, N*2+1);
	tot+=p.second;

	fprintf(g, "%d\n", tot);

	fclose(f);
	fclose(g);
	return 0;
}