Cod sursa(job #1887110)

Utilizator GinguIonutGinguIonut GinguIonut Data 21 februarie 2017 12:51:41
Problema Arbore partial de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 8.63 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>

#define INF 1000000000
#define coordMax 1000001
#define nMax 101
#define edgesMax 10001
#define pb push_back
#define mkp make_pair
#define x first
#define y second

using namespace std;

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

int op, n, conex[nMax], viz[nMax], heap[nMax], poz[nMax], nrEl, nrConex;
double distMax, distApm[nMax];
pair<double, double> tr[nMax][4];
vector<pair<int, double> > G[nMax];

double dist(double x1, double y1, double x2, double y2)
{
    return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}

double determinant(double x1, double y1, double x2, double y2, double x3, double y3)
{
    return x1*y2+y1*x3+x2*y3-y2*x3-y1*x2-x1*y3;
}

void upDateHeap(int pozi)
{
    int po;
    while(pozi/2)
    {
        po=pozi/2;
        if(distApm[heap[po]]>distApm[heap[pozi]])
        {
            swap(heap[po], heap[pozi]);
            swap(poz[heap[po]], poz[heap[pozi]]);
            pozi=po;
        }
        else
            break;
    }
}

void insertHeap(int node)
{
    heap[++nrEl]=node;
    poz[node]=nrEl;
    upDateHeap(poz[node]);
}
void downDateHeap(int pozi)
{
    int po;
    while(pozi*2<=nrEl)
    {
        po=pozi*2;
        if(po+1<=nrEl && distApm[heap[po]]>distApm[heap[po+1]])
            po++;
        if(distApm[heap[po]]<distApm[heap[pozi]])
        {
            swap(heap[po], heap[pozi]);
            swap(poz[heap[po]], poz[heap[pozi]]);
            pozi=po;
        }
        else
            break;
    }
}

void inApm(int node)
{
    for(vector<pair<int, double> >::iterator it=G[node].begin(); it!=G[node].end(); it++)
    {
        int fiu=it->first;
        double cost=it->second;
        distApm[fiu]=min(distApm[fiu], cost);
        if(viz[fiu]==0)
        {
            viz[fiu]=1;
            insertHeap(fiu);
        }
    }
}

int extractHeap(int pozi)
{
    int node=heap[pozi];
    swap(heap[pozi], heap[nrEl]);
    swap(poz[heap[pozi]], poz[heap[nrEl]]);
    nrEl--;
    downDateHeap(1);
    poz[node]=0;
    return node;
}

void dfs(int node)
{
    viz[node]=1;
    conex[nrConex]++;

    for(vector<pair<int, double> >::iterator it=G[node].begin(); it!=G[node].end(); it++)
    {
        int fiu=it->first;
        if(viz[fiu])
            continue;
        dfs(fiu);
    }
}

pair<pair<double, double>, double> ecuatieDreapta(double x1, double y1, double x2, double y2)
{
    pair<pair<double, double>, double> Sol;
    Sol.x.x=x2-x1;
    Sol.x.y=y1-y2;
    Sol.y=x1*y2-y1*x2;
    return Sol;
}

pair<double, double> intersectDrepte(pair<pair<double, double>, double> ec1, pair<pair<double, double>, double> ec2)
{
    pair<double, double> Sol;
    if(ec1.x.x==0)
        swap(ec1, ec2);
    Sol.x=(ec2.x.x*ec1.y-ec1.x.x*ec2.y)/(ec1.x.x*ec2.x.y-ec1.x.y*ec2.x.x);
    Sol.y=(-ec1.x.y*Sol.x-ec1.y)/ec1.x.x;
    return Sol;
}

int main()
{
    fin>>op>>n>>distMax;
    for(int i=1; i<=n; i++)
    {
        for(int j=0; j<3; j++)
            fin>>tr[i][j].x>>tr[i][j].y;
        tr[i][3]=tr[i][0];
    }

    for(int i=1; i<=n; i++)
    {
        for(int j=0; j<3; j++)
        {
            pair<pair<double, double>, double> ecVert=ecuatieDreapta(tr[i][j].x, tr[i][j].y, tr[i][j].x, tr[i][j].y+1);
            pair<pair<double, double>, double> ecOriz=ecuatieDreapta(tr[i][j].x, tr[i][j].y, tr[i][j].x+1, tr[i][j].y);
            for(int t=1; t<=n; t++)
            {
                if(i!=t)
                {
                    for(int k=0; k<3; k++)
                    {
                        double distantaMin=INF;
                        pair<pair<double, double>, double> ecDr=ecuatieDreapta(tr[t][k].x, tr[t][k].y, tr[t][k+1].x, tr[t][k+1].y);
                        if(tr[t][k].x!=tr[t][k+1].x || (tr[t][k].x==tr[t][k+1].x && tr[t][k].x==tr[i][j].x))//intersectia cu verticala
                        {
                                pair<double, double> pctIntersect=intersectDrepte(ecDr, ecVert);
                                if(tr[i][j].x==tr[t][k].x && tr[i][j].x==tr[t][k+1].x)
                                {
                                    if(tr[t][k].y<tr[i][j].y)
                                        pctIntersect=mkp(tr[t][k].x, tr[t][k+1].y);
                                    else
                                        pctIntersect=mkp(tr[t][k].x, tr[t][k].y);
                                    double distanta=dist(tr[i][j].x, tr[i][j].y, pctIntersect.x, pctIntersect.y);
                                    distantaMin=min(distantaMin, distanta);
                                }
                                else
                                {
                                    double det1=determinant(tr[i][j].x, coordMax, tr[i][j].x, 0, tr[t][k].x, tr[t][k].y);
                                    double det2=determinant(tr[i][j].x, coordMax, tr[i][j].x, 0, tr[t][k+1].x, tr[t][k+1].y);
                                    if((det1<=0 && det2>=0) || (det1>=0 && det2<=0))
                                    {
                                        double distanta=dist(tr[i][j].x, tr[i][j].y, pctIntersect.x, pctIntersect.y);
                                        distantaMin=min(distantaMin, distanta);
                                    }
                                }
                        }
                        if(tr[t][k].y!=tr[t][k+1].y || (tr[t][k].y==tr[t][k+1].y && tr[t][k].y==tr[i][j].y))//intersectia cu orizontala
                        {
                                pair<double, double> pctIntersect=intersectDrepte(ecDr, ecOriz);
                                if(tr[i][j].y==tr[t][k].y && tr[i][j].y==tr[t][k+1].y)
                                {
                                    if(tr[t][k].x<tr[i][j].x)
                                        pctIntersect=mkp(tr[t][k+1].x, tr[t][k].y);
                                    else
                                        pctIntersect=mkp(tr[t][k].x, tr[t][k].y);
                                    double distanta=dist(tr[i][j].x, tr[i][j].y, pctIntersect.x, pctIntersect.y);
                                    distantaMin=min(distantaMin, distanta);
                                }
                                else
                                {
                                    double det1=determinant(0, tr[i][j].y, coordMax, tr[i][j].y, tr[t][k].x, tr[t][k].y);
                                    double det2=determinant(0, tr[i][j].y, coordMax, tr[i][j].y, tr[t][k+1].x, tr[t][k+1].y);
                                    if((det1<=0 && det2>=0) || (det1>=0 && det2<=0))
                                    {
                                        double distanta=dist(tr[i][j].x, tr[i][j].y, pctIntersect.x, pctIntersect.y);
                                        distantaMin=min(distantaMin, distanta);
                                    }
                                }
                        }
                        if(distantaMin<=distMax)
                        {
                            G[i].pb(mkp(t, distantaMin));
                            G[t].pb(mkp(i, distantaMin));
                        }
                    }
                }
            }
        }
    }
    if(op==1 || op==2)
    {
        for(int i=1; i<=n; i++)
        {
            if(viz[i]==0)
            {
                nrConex++;
                dfs(i);
            }
        }
        if(op==1)
        {
            int Sol=0;
            for(int i=1; i<=nrConex; i++)
                Sol+=conex[i]-1;
            fout<<Sol;
            return 0;
        }
        if(op==2)
        {
            int Sol=0;
            for(int i=1; i<=nrConex; i++)
                Sol+=conex[i]*(conex[i]-1)/2;
            fout<<Sol;
            return 0;
        }
    }
    else
    {
        double Sol=0;
        for(int i=1; i<=n; i++)
            distApm[i]=INF;
        for(int i=1; i<=n; i++)
        {
            if(viz[i]==0)
            {
                viz[i]=1;
                distApm[i]=0;
                inApm(i);

                while(nrEl)
                {
                    int node=extractHeap(1);
                    inApm(node);
                    Sol+=distApm[node];
                    for(vector<pair<int, double> >::iterator it=G[node].begin(); it!=G[node].end(); it++)
                    {
                        int fiu=it->first;
                        if(poz[fiu])
                            upDateHeap(poz[fiu]);
                    }
                }
            }
        }
        fout<<Sol;
    }
}