답안 #374249

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
374249 2021-03-07T00:52:25 Z LucaDantas 시간이 돈 (balkan11_timeismoney) C++17
80 / 100
481 ms 748 KB
#include<bits/stdc++.h>
using namespace std;

#define int long long
#define pb push_back

constexpr int maxn = 210, maxm = 1e4+10;

int n, m;

struct DSU
{
	int pai[maxn], peso[maxn];
	bool get_ans = 0;
	void init() { for(int i = 0; i < n; i++) pai[i] = i, peso[i] = 1; }
	int find(int x) { return pai[x]==x?x:pai[x]=find(pai[x]); }
	bool join(int a, int b) {
		int x = a, y = b;
		a = find(a), b = find(b);
		if(a == b) return 0;
		if(peso[a] < peso[b])
			swap(a, b);
		pai[b] = a;
		peso[a] += peso[b];
		if(get_ans) printf("%lld %lld\n", x, y);
		return 1;
	}
} dsu;


struct Edge
{
	int a, b, t, c;
} edges[maxm];

long long val(Edge x, int A, int B) { 
	return 1ll * x.t * A + 1ll * x.c * B;
}

pair<int,int> get(int A, int B) {
	// printf("%lld %lld\n", A, B);
	dsu.init();
	pair<int,int> ans = {0, 0};
	sort(edges, edges+m, [A, B](Edge x, Edge y){
		return val(x, A, B) < val(y, A, B);
	});
	for(int i = 0; i < m; i++)
		if(dsu.join(edges[i].a, edges[i].b))
			ans.first += edges[i].t, ans.second += edges[i].c;
	return ans;
}

struct ANS {
	long long v; int t, c, A, B;
	ANS() : v(0x3f3f3f3f3f3f3f3f) {}
	ANS(int T, int C, int a, int b) {
		v = 1ll*T*C, t = T, c = C, A = a, B = b;
	}
} ans;

ANS min(ANS a, ANS b) {
	if(a.v < b.v) return a;
	return b;
}

using pii = pair<int,int>;
bool cross(pii a, pii b, pii c) {
	b.first -= a.first;
	c.first -= a.first;
	b.second -= a.second;
	c.second -= a.second;
	return (1ll * b.first * c.second - 1ll * b.second * c.first) != 0;
}

void solve(pii l, pii r) {
	// we want to find the vector parallel to the line between l and r
	// because the point that minimizes the dot with such vector is
	// the 'furthest point' in the direction of that line

	// we can find such vector by taking the slope of the line and
	// using the standard formula to calculate the slope of the parelell
	// line.


	int x = r.first - l.first, y = r.second - l.second;
	pii m = get(-y, x); // keep things positive for simplicity
	
	ans = min(ans, ANS(m.first, m.second, -y, x));
	if(cross(l, m, r)) {
		solve(l, m);
		solve(m, r);
	}
}

int32_t main() {
	scanf("%lld %lld", &n, &m);
	for(int i = 0; i < m; i++) {
		int a, b, t, c; scanf("%lld %lld %lld %lld", &a, &b, &t, &c);
		edges[i] = {a, b, t, c};
	}
	pair<int,int> l = get(1, 0);
	pair<int,int> r = get(0, 1);
	ans = min(ANS(l.first, l.second, 1, 0), ANS(r.first, r.second, 0, 1));
	if(l != r)
		solve(l, r);
	dsu.get_ans = 1;
	printf("%lld %lld\n", ans.t, ans.c);
	get(ans.A, ans.B);
}

Compilation message

timeismoney.cpp: In function 'int32_t main()':
timeismoney.cpp:96:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   96 |  scanf("%lld %lld", &n, &m);
      |  ~~~~~^~~~~~~~~~~~~~~~~~~~~
timeismoney.cpp:98:24: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   98 |   int a, b, t, c; scanf("%lld %lld %lld %lld", &a, &b, &t, &c);
      |                   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 364 KB Output is correct
2 Correct 1 ms 364 KB Output is correct
3 Correct 1 ms 364 KB Output is correct
4 Correct 1 ms 364 KB Output is correct
5 Correct 1 ms 364 KB Output is correct
6 Correct 1 ms 364 KB Output is correct
7 Correct 2 ms 364 KB Output is correct
8 Correct 5 ms 620 KB Output is correct
9 Correct 1 ms 364 KB Output is correct
10 Correct 1 ms 364 KB Output is correct
11 Incorrect 1 ms 364 KB Output isn't correct
12 Correct 1 ms 364 KB Output is correct
13 Correct 1 ms 364 KB Output is correct
14 Correct 4 ms 364 KB Output is correct
15 Incorrect 3 ms 364 KB Output isn't correct
16 Correct 54 ms 364 KB Output is correct
17 Correct 55 ms 364 KB Output is correct
18 Correct 57 ms 364 KB Output is correct
19 Incorrect 473 ms 748 KB Output isn't correct
20 Incorrect 481 ms 748 KB Output isn't correct