Cod sursa(job #2875609)

Utilizator FrostfireMagirescu Tudor Frostfire Data 21 martie 2022 23:42:16
Problema Paznici2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.46 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#define NMAX 200
#define inf 1000000000

using namespace std;

ifstream fin("paznici2.in");
ofstream fout("paznici2.out");

int n, ANS, dist[2*NMAX+10], p[2*NMAX+10], ans[NMAX+10], cost[NMAX+10][NMAX+10], Dist[NMAX+10][NMAX+10];
vector <int> sol[NMAX+10];
queue <int> Q;

struct muchie{
	int nod, flow, cost;
};

vector <muchie> nod[2*NMAX+10];

bool addFlow(){

	dist[0] = 0;
	for(int i=1; i<=2*n+1; i++)
		dist[i] = inf, p[i] = -1;
	p[0] = 0;

	Q.push(0);
	while(!Q.empty()){
		int x = Q.front();
		Q.pop();
		for(auto u : nod[x])
			if(u.flow && dist[x] + u.cost < dist[u.nod]){
				dist[u.nod] = dist[x] + u.cost;
				Q.push(u.nod);
				p[u.nod] = x;
			}
	}

	if(p[2*n+1] != -1)
		ANS += dist[2*n+1];

	return p[2*n+1] != -1;

}

int main(){

	fin >> n;
	for(int i=1; i<=n; i++){
		nod[0].push_back({i, 1, 0});
		nod[i].push_back({0, 0, 0});
		for(int j=1; j<=n; j++){
			int x;
			fin >> x;
			nod[i].push_back({n + j, 1, x});
			nod[n+j].push_back({i, 0, -x});
			cost[i][j] = x;
		}
		nod[i+n].push_back({2 * n + 1, 1, 0});
		nod[2*n+1].push_back({i + n, 0, 0});
	}

	while(addFlow()){
		int curr = 2 * n + 1;
		while(curr){
			int pr = p[curr];

			for(int i=0; i<nod[pr].size(); i++){
				muchie u = nod[pr][i];
				if(u.nod == curr){
					nod[pr][i].flow--;
					break;
				}
			}
			for(int i=0; i<nod[curr].size(); i++){
				muchie u = nod[curr][i];
				if(u.nod == pr){
					nod[curr][i].flow++;
					break;
				}
			}
			curr = pr;
		}
	}

	for(int i=1; i<=n; i++)
		for(auto u : nod[i])
			if(u.nod > n && u.nod <= 2 * n && !u.flow){
				ans[i] = u.nod - n;
				sol[u.nod - n].push_back(i);
			}
	
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++){
			if(i != j)
				Dist[i][j] = cost[i][ans[j]] - cost[i][ans[i]];
			else
				Dist[i][i] = inf;
		}
	
	for(int k=1; k<=n; k++)
		for(int i=1; i<=n; i++)
			if(k != i)
				for(int j=1; j<=n; j++)
					if(k != j && i != j)
						Dist[i][j] = min(Dist[i][j], Dist[i][k] + Dist[k][j]);

	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++)
			if(i != j && cost[i][ans[j]] - cost[i][ans[i]] + Dist[j][i] == 0)
				sol[ans[j]].push_back(i);

	fout << ANS << '\n';

	for(int i=1; i<=n; i++){
		sort(sol[i].begin(), sol[i].end());
		fout << sol[i].size() << ' ';
		for(auto u : sol[i])
			fout << u << ' ';
		fout << '\n';
	}

	return 0;
}