Cod sursa(job #3004076)

Utilizator DKMKDMatei Filibiu DKMKD Data 16 martie 2023 09:31:59
Problema Lupul Urias si Rau Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.11 kb
#include <bits/stdc++.h>
#define in "elicoptere.in"
#define out "elicoptere.out"
using namespace std;
ifstream fin(in);
ofstream fout(out);

struct Pct
{
    double x,y;
};

struct muchie
{
    int x;
    int y;
    double cost;
};

short cer;
int n,k,nrc;
int c[103],T[103];
int viz[103];
int con[103];
vector <muchie> v;
vector <int> L[103];
Pct t[103][3]; /// t[i][0] = primul vf al triunghiului i, etc.

void Read()
{
    int i;

    fin >> cer;
    fin >> n >> k;
    for (i = 1; i <= n; i++)
    {
        fin >> t[i][0].x >> t[i][0].y;
        fin >> t[i][1].x >> t[i][1].y;
        fin >> t[i][2].x >> t[i][2].y;
    }
}

/// distanta pe orizontala de la A la [BC]
double DistH(Pct A, Pct B, Pct C)
{
    if ((B.y <= A.y && A.y <= C.y) || (C.y <= A.y && A.y <= B.y))
    {
        double a,b,c,xm;

        a = B.y - C.y;
        b = C.x - B.x;
        c = B.x * C.y - C.x * B.y;
        xm = (-c - b * A.y) / a;

        return abs(A.x - xm);
    }
    return k+1;
}

double DistV(Pct A, Pct B, Pct C)
{
    if ((B.x <= A.x && A.x <= C.x) || (C.x <= A.x && A.x <= B.x))
    {
        double a,b,c,ym;

        a = B.y - C.y;
        b = C.x - B.x;
        c = B.x * C.y - C.x * B.y;
        ym = (-c - a * A.x) / b;

        return abs(A.y - ym);
    }
    return k+1;
}

/// distanta dintre doua insule de indici p si q
double Dist(int p, int q)
{
    double mini = k+1;
    int i,j,j1;

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 2; j++)
            for (j1 = j+1; j1 < 3; j1++)
            {
                mini = min(mini,DistH(t[p][i],t[q][j],t[q][j1]));
                mini = min(mini,DistV(t[p][i],t[q][j],t[q][j1]));
            }
    }

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 2; j++)
            for (j1 = j+1; j1 < 3; j1++)
            {
                mini = min(mini,DistH(t[q][i],t[p][j],t[p][j1]));
                mini = min(mini,DistV(t[q][i],t[p][j],t[p][j1]));
            }
    }
    return mini;
}

void MakeGraph()
{
    int i,j;
    double d;
    muchie w;

    for (i = 1; i < n; i++)
        for (j = i+1; j <= n; j++)
        {
            d = Dist(i,j);
            if (d <= k)
            {
                w.x = i;
                w.y = j;
                w.cost = d;
                L[i].push_back(j);
                L[j].push_back(i);
                v.push_back(w);
            }
        }
}

void DFS(int k, int &noduri)
{
    noduri++;
    viz[k] = 1;
    c[nrc] = k;
    for (auto i : L[k])
        if (viz[i] == 0) DFS(i,noduri);
}

inline bool cmp(muchie A, muchie B)
{
    return A.cost < B.cost;
}

void Union(int x, int y)
{
    T[x] = y;
}

int Find(int x)
{
    int r,y;

    r = x;
    while (T[r] != 0)
        r = T[r];
    /// comprimarea drumului
    while (x != r)
    {
        y = T[x];
        T[x] = r;
        x = y;
    }
    return r;
}

void Kruskal()
{
    int x,y;
    double costmin = 0;

    sort(v.begin(),v.end(),cmp);
    for (auto i : v)
    {
        x = Find(i.x);
        y = Find(i.y);
        if (x != y)
        {
            costmin += i.cost;
            Union(x,y);
        }
    }
    fout << setprecision(4) << fixed << costmin << "\n";
}

int main()
{
    Read();
    MakeGraph();
    if (cer == 1)
    {
        int noduri = 0;

        nrc = 0;
        for (int i = 1; i <= n; i++)
            if (viz[i] == 0)
            {
                nrc++; noduri = 0;
                DFS(i,noduri);
                con[nrc] = noduri;
            }
        fout << n - nrc << "\n";
    }
    else if (cer == 2)
    {
        long long sol = 0;
        int noduri = 0, i;

        nrc = 0;
        for (i = 1; i <= n; i++)
            if (viz[i] == 0)
            {
                nrc++; noduri = 0;
                DFS(i,noduri);
                con[nrc] = noduri;
            }
        for (i = 1; i <= nrc; i++)
            sol += (con[i] * (con[i] - 1) / 2);
        fout << sol << "\n";
    }
    else Kruskal();

    fin.close();
    fout.close();
    return 0;
}