2018년 2월 17일 토요일

2463 비용

2463 비용 https://www.acmicpc.net/problem/2463

Cost(u,v)uv사이의 경로가 존재하지 않을 때 까지 
그래프 상의 최소가중치 간선들을 지우고 그 값들의 합이다.
모든 u<v들에 대해 Cost(u,v)들의 합을 구하는 문제이다.

최소가중치 간선을 대신해 최대가중치 간선에 대해 생각해보자.
어떠한 정점 u,v상에 경로가 존재하지 않는다면 uv를 잇는 가장 큰 가중치 간선 보다 
작거나 같은 간선들의 합이 pu = u에 속해있는 disjoint set
pv = v에 속해있는 disjoint set 일 때 Cost(pu, pv)가 될 것이다.
즉, 위에서 초록색 간선으로 u,v상에 경로가 존재하지 않고 초록색 간선으로 연결하려 할 때
pupv의 모든 쌍들의 Cost(pu,pv)를 구할 수 있다.


#include <cstdio>
#include <iostream>
#include <string>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <iomanip>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
using namespace std;
#define mp(a,b) make_pair(a,b)
#define mt(a,b,c) mp(a,mp(b,c))
#define mf(a,b,c,d) mp(mp(a,b),mp(c,d))
#define PI 3.14159265358979323846264
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define mod (ll)(1e9)
ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
int dy[] = { 001-1 };     //동, 서, 남, 북        
int dx[] = { 1-100 };
const int MAXN = 100000 + 5;
int N, M;
vector<pair<intpair<intint>>> edge;
int par[MAXN], sze[MAXN];
ll sum;
int find(int x) {
    if (par[x] == x) return x;
    return par[x] = find(par[x]);
}
void merge(int u, int v) {
    if (sze[u] < sze[v]) swap(u, v);
    par[v] = u;
    sze[u] += sze[v];
    sze[v] = 1;
}
int main() {
    scanf("%d%d"&N, &M);
    for (int n = 1; n <= N; n++) par[n] = n, sze[n] = 1;
    for (int m = 0; m < M; m++) {
        int u, v, d;
        scanf("%d%d%d"&u, &v, &d);
        edge.push_back({ d,{u,v} });
        sum += d;
    }
    ll ans = 0;
    sort(edge.begin(), edge.end());
    for (int m = M - 1; m >= 0; m--) {
        int u = edge[m].second.first, v = edge[m].second.second;
        int tcost = edge[m].first;
        int fu = find(u), fv = find(v);
        if (fu != fv) {
            ans += ((((ll)sze[fu] * sze[fv]) % mod) *sum) % mod;
            ans %= mod;
            merge(fu, fv);
        }
        sum -= tcost;
    }
    printf("%lld\n", ans);
    return 0;
}
cs

2018년 2월 6일 화요일

Atcoder B - Two Arrays

Atcoder B - Two Arrays https://apc001.contest.atcoder.jp/tasks/apc001_b

N개의 숫자가 차있는 배열 A,B가 주어진다.
operation는 배열 A에 있는 원소 하나를 +2하고 배열 B에있는 원소 하나를 +1한다.
operation을 무한히 할 때 두 배열이 완전 일치하는지 판단하는 문제다.

배열A의 원소들의 합을 $q$, 배열 B의 원소들의 합을 $p$라 할 때 $q+2x=p+x$가 성립해야 한다.
즉, $q-p < 0$이면 모순이다.
또한 배열A의 원소 $a_{n}$은 결국 배열B의 원소 $b_{n}$과 동일해 져야 한다.
각각의 원소들을 가능한 동일하도록 맞춰주고 맞춰주는데 드는 횟수가 
배열B가 더 작거나 같으면 성립한다.
#include <cstdio>
typedef long long ll;
int N;
int a[10001];
int b[10001];
ll p, q;
int main(){
    scanf("%d"&N);
    for (int n = 0; n < N; n++scanf("%d"&a[n]), p += a[n];
    for (int n = 0; n < N; n++scanf("%d"&b[n]), q += b[n];
    if (q - p < 0return !printf("No\n");
    ll sa = 0, sb = 0;
    for (int n = 0; n < N; n++){
        if (a[n] > b[n]){
            sb += a[n] - b[n];
        }
        else if (a[n] < b[n]){
            int t = (b[n] - a[n] + 1>> 1;
            sa += t;
            sb += a[n] + 2 * t - b[n];
        }
    }
    if (sa >= sb) printf("Yes\n");
    else printf("No\n");
    return 0;
}
cs