Cod sursa(job #1417292)

Utilizator alex_HarryBabalau Alexandru alex_Harry Data 10 aprilie 2015 00:25:42
Problema Cuplaj maxim de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.76 kb
#include <fstream>
#include <queue>
using namespace std;
ifstream f("naveplanare.in");
ofstream g("naveplanare.out");
const int NMax = 405;
const short INF = 32000;
short MinLine,Distance[2705],Father[2705],Flow[2705][2705],Capacity[2705][2705];
int N,K,source,sink,ans;
bool InQ[2705];
pair <short,short> Point[NMax];
vector < pair<short,short> > G[2705];
queue <short> Q;
void Read()
{
    f>>N>>K;
    for(int i=1;i<=N;i++)
        f>>Point[i].first>>Point[i].second;
}
void init()
{
    for(int i=source;i<=sink;i++)
        Father[i]=-1,InQ[i]=0;
    for(int i=1;i<=sink;i++)
        Distance[i]=INF;
    Q.push(source);
    Distance[source]=0;
    InQ[source]=1;
}

bool bellmanFord()
{
    init();
    while(!Q.empty())
    {
        int node=Q.front();
        Q.pop();
        InQ[node]=0;
        for(int i=0;i<G[node].size();i++)
        {
            short int cost=G[node][i].second,neighb=G[node][i].first;
            if(Distance[neighb]>Distance[node]+cost && Capacity[node][neighb]-Flow[node][neighb]>0)
            {
                Father[neighb]=node;
                Distance[neighb]=Distance[node]+cost;
                if(InQ[neighb]==0)
                {
                    Q.push(neighb);
                    InQ[neighb]=1;
                }
            }
        }
    }
    return Father[sink]!=-1;
}
inline int mod(int x)
{
    return max(x,-x);
}
short min(short a,short b)
{
    if(a<b)
        return a;
    return b;
}
void solveLine()
{
    int MinFlow=0;
    for(int i=1;i<=N;i++)
    {
        short x=Point[i].first;
        for(short j=-N-1000;j<=1000+N;j++)
        {
            G[i].push_back(make_pair(N+j+N+1000+1,mod(x-j))),Capacity[i][N+j+N+1000+1]=1;
            G[N+j+N+1000+1].push_back(make_pair(i,-mod(x-j)));
        }

    }
    source=0;
    sink=N+2402;
    for(int i=1;i<=N;i++)
    {
        Capacity[source][i]=1;
        G[source].push_back(make_pair(i,0));
        G[i].push_back(make_pair(source,0));
    }
    for(int i=N+1;i<=N+2401;i++)
    {
        Capacity[i][sink]=1;
        G[sink].push_back(make_pair(i,0));
        G[i].push_back(make_pair(sink,0));
    }
    int f=0;
    while(bellmanFord() && f<K)
    {
        short flow=1;
        for(int node=sink;node!=source;node=Father[node])
            Flow[Father[node]][node]+=flow,Flow[node][Father[node]]-=flow;
        f+=flow;MinFlow+=Distance[sink]*flow;
    }
    ans+=MinFlow;
}

void solveCol()
{
    int MinFlow=0;
     for(int i=1;i<=N;i++)
    {
        short x=Point[i].second;
        for(short j=-N-1000;j<=1000+N;j++)
        {
            G[i].push_back(make_pair(N+j+N+1000+1,mod(x-j))),Capacity[i][N+j+N+1000+1]=1;
            G[N+j+N+1000+1].push_back(make_pair(i,-mod(x-j)));
        }

    }
    source=0;
    sink=N+2402;
    for(int i=1;i<=N;i++)
    {
        Capacity[source][i]=1;
        G[source].push_back(make_pair(i,0));
        G[i].push_back(make_pair(source,0));
    }
    for(int i=N+1;i<=N+2401;i++)
    {
        Capacity[i][sink]=1;
        G[sink].push_back(make_pair(i,0));
        G[i].push_back(make_pair(sink,0));
    }
    int f=0;
    while(bellmanFord() && f<K)
    {
        short flow=1;
        for(int node=sink;node!=source;node=Father[node])
            Flow[Father[node]][node]+=flow,Flow[node][Father[node]]-=flow;
        f+=flow;MinFlow+=Distance[sink]*flow;
    }
    ans+=MinFlow;
}
int main()
{
    Read();
    solveLine();
    for(int i=0;i<=2700;i++)
        for(int j=0;j<=2700;j++)
            Capacity[i][j]=Capacity[j][i]=Flow[i][j]=Flow[j][i]=0;
    for(int i=0;i<=N+2402;i++)
        G[i].clear();
    solveCol();
    g<<ans<<"\n";
    /*for(int i=1;i<=200;i++)
        g<<"1000 -1000\n";*/
    return 0;
}