結果
| 問題 | No.1316 Maximum Minimum Spanning Tree |
| コンテスト | |
| ユーザー |
hitonanode
|
| 提出日時 | 2020-12-11 01:38:49 |
| 言語 | C++17(gcc12) (gcc 12.4.0 + boost 1.90.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 6,188 bytes |
| 記録 | |
| コンパイル時間 | 7,078 ms |
| コンパイル使用メモリ | 368,032 KB |
| 実行使用メモリ | 7,968 KB |
| 最終ジャッジ日時 | 2026-06-15 21:28:13 |
| 合計ジャッジ時間 | 11,493 ms |
|
ジャッジサーバーID (参考情報) |
judge1_1 / judge2_1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 WA * 1 |
| other | AC * 2 WA * 1 TLE * 1 -- * 74 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#include <boost/multiprecision/cpp_dec_float.hpp>
// Simplex from <https://kopricky.github.io/code/Computation_Advanced/simplex.html>
// using Float = long double;
using Float = boost::multiprecision::cpp_dec_float_100;
#define EPS 1e-30
// max c * x s.t. A*x <= b, x >= 0
class Simplex {
private:
using Arr = vector<Float>;
using Mat = vector<vector<Float> >;
int* index;
Float** a;
int row, column, L;
void Set(const Mat& A, const Arr& b, const Arr& c){
infinity = none = false;
row = A.size(),column = A[0].size() + 1;
index = new int[row + column];
int i, j;
for(i = 0; i < row + column; i++) index[i] = i;
L = row;
a = new Float*[row + 2];
for(i = 0; i < row + 2; i++) a[i] = new Float[column + 1];
for(i = 0; i < row; i++){
for(j = 0; j < column - 1; j++) a[i][j] = -A[i][j];
a[i][column-1] = 1, a[i][column] = b[i];
if(a[L][column] > a[i][column]) L = i;
}
for(j = 0; j < column - 1; j++) a[row][j] = c[j];
a[row+1][column-1] = -1;
}
void solve(){
int E, i, j;
int* ls = new int[column + 2];
for(E = column - 1;;){
if(L < row){
swap(index[E], index[L + column]);
a[L][E] = 1 / a[L][E];
int prv = column + 1;
for(j = 0; j < column + 1; j++){
if(j != E){
a[L][j] *= -a[L][E];
if(abs(a[L][j]) > EPS) ls[prv] = j, prv = j;
}
}
ls[prv] = column + 1;
for(i = 0; i < row + 2; i++){
if(abs(a[i][E]) < EPS || i == L) continue;
for(j = ls[column + 1]; j < column + 1; j = ls[j]){
a[i][j] += a[i][E] * a[L][j];
}
a[i][E] *= a[L][E];
}
}
E = -1;
// Float pre = EPS;
for(j = 0; j < column; j++){
if(E < 0 || index[E] > index[j]){
if(a[row + 1][j] > EPS || (abs(a[row + 1][j]) < EPS && a[row][j] > EPS)) E = j;
// if(a[row + 1][j] > pre) E = j, pre = a[row + 1][j];
// else if(abs(a[row + 1][j]) < EPS && a[row][j] > pre) E = j, pre = a[row][j];
}
}
if(E < 0) break;
L = -1;
for(i = 0; i < row; i++){
if(a[i][E] < -EPS){
if(L < 0) L = i;
else if(a[L][column] / a[L][E] - a[i][column] / a[i][E] < -EPS) L = i;
else if(a[L][column] / a[L][E] - a[i][column] / a[i][E] < EPS && index[L] > index[i]) L = i;
// if(L < 0 || a[L][column] / a[L][E] - a[i][column] / a[i][E] < EPS) L = i;
}
}
if(L < 0){
infinity = true;
return;
}
}
if(a[row + 1][column] < -EPS){
none = true;
return;
}
x.assign(column - 1, 0);
for(i = 0; i < row; i++){
if(index[column + i] < column - 1) x[index[column + i]] = a[i][column];
}
ans = a[row][column];
}
public:
bool infinity, none;
Float ans;
Arr x;
Simplex(const Mat& A, const Arr& b, const Arr& c){
Set(A,b,c);
solve();
}
};
// UnionFind Tree (0-indexed), based on size of each disjoint set
struct UnionFind {
std::vector<int> par, cou;
UnionFind(int N = 0) : par(N), cou(N, 1) { iota(par.begin(), par.end(), 0); }
int find(int x) { return (par[x] == x) ? x : (par[x] = find(par[x])); }
bool unite(int x, int y) {
x = find(x), y = find(y);
if (x == y) return false;
if (cou[x] < cou[y]) std::swap(x, y);
par[y] = x, cou[x] += cou[y];
return true;
}
int count(int x) { return cou[find(x)]; }
bool same(int x, int y) { return find(x) == find(y); }
};
int main()
{
cin.tie(nullptr);
ios::sync_with_stdio(false);
int N, M, K;
cin >> N >> M >> K;
vector<int> A(M), B(M), C(M), D(M);
vector<pair<int, int>> c2i;
for (int eid = 0; eid < M; eid++) {
cin >> A[eid] >> B[eid] >> C[eid] >> D[eid];
A[eid]--, B[eid]--, c2i.emplace_back(C[eid], eid);
}
sort(c2i.begin(), c2i.end());
UnionFind uf(N);
vector<int> mstedge(M);
vector<vector<pair<int, int>>> tree(N);
vector<int> vpar(N, -1), epar(N, -1), depth(N);
long long ret = 0;
vector<long long> xdefault(M);
for (const auto [cost, eid] : c2i) {
const int u = A[eid], v = B[eid];
if (uf.unite(u, v)) {
mstedge[eid] = 1;
ret += (long long)C[eid] * K;
tree[u].emplace_back(v, eid);
tree[v].emplace_back(u, eid);
}
}
auto dfs = [&](auto &&self, int now, int prv, int dnow) -> void {
depth[now] = dnow;
for (const auto [nxt, eid] : tree[now]) {
if (nxt != prv) {
vpar[nxt] = now, epar[nxt] = eid;
self(self, nxt, now, dnow + 1);
}
}
};
dfs(dfs, 0, -1, 0);
vector<vector<Float>> matA(1, vector<Float>(M, 0));
vector<Float> vecb{1};
vector<Float> vecc(M);
auto add_constraint = [&](int emst, int eadd) {
vector<Float> v(M);
v[emst] = 1, v[eadd] = -1;
matA.emplace_back(v);
vecb.emplace_back(C[eadd] - C[emst]);
};
for (int eid = 0; eid < M; eid++) {
vecc[eid] = mstedge[eid] * K - D[eid];
if (!mstedge[eid]) {
int u = A[eid], v = B[eid];
while (depth[u] > depth[v]) add_constraint(epar[u], eid), u = vpar[u];
while (depth[v] > depth[u]) add_constraint(epar[v], eid), v = vpar[v];
while (u != v) add_constraint(epar[u], eid), u = vpar[u], add_constraint(epar[v], eid), v = vpar[v];
}
}
Simplex simplex(matA, vecb, vecc);
if (simplex.infinity) puts("-1");
else cout << ret + llround(simplex.ans) << '\n';
}
hitonanode