Cod sursa(job #1757717)

Utilizator chiriacandrei25Chiriac Andrei chiriacandrei25 Data 15 septembrie 2016 18:36:24
Problema Traseu Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.32 kb
#include <bits/stdc++.h>
#define Nmax 65
#define pb push_back
#define INF 1000000000

using namespace std;

int d[Nmax][Nmax],in[Nmax],out[Nmax];
int v1[Nmax],v2[Nmax],l1,l2,S,D,prv[Nmax],dist[Nmax];
int F[Nmax][Nmax],Cost[Nmax][Nmax],C[Nmax][Nmax],n;
bool viz[Nmax];
vector <int> L[Nmax];
queue <int> Q;

inline void add_edge(int x, int y, int cap, int cost)
{
    L[x].pb(y); L[y].pb(x);
    C[x][y]=cap; Cost[x][y]=cost;
    Cost[y][x]=-cost;
}

inline bool Bellman()
{
    int i,nod;
    for(i=1;i<=D;++i)
    {
        dist[i]=INF; viz[i]=0;
    }
    Q.push(S); viz[S]=1;
    while(!Q.empty())
    {
        nod=Q.front();
        Q.pop(); viz[nod]=0;
        for(auto it : L[nod])
            if(F[nod][it]<C[nod][it] && dist[it]>dist[nod]+Cost[nod][it])
            {
                dist[it]=dist[nod]+Cost[nod][it];
                prv[it]=nod;
                if(!viz[it])
                {
                    Q.push(it); viz[it]=1;
                }
            }
    }
    return (dist[D]!=INF);
}

inline long long Min_Flow()
{
    long long cost=0;
    int flow,min_flow,i;
    while(Bellman())
    {
        min_flow=INF;
        for(i=D;i!=S;i=prv[i]) min_flow=min(min_flow,C[prv[i]][i]-F[prv[i]][i]);
        for(i=D;i!=S;i=prv[i])
        {
            F[prv[i]][i]+=min_flow;
            F[i][prv[i]]-=min_flow;
        }
        cost+=1LL*min_flow*dist[D];
    }
    return cost;
}

int main()
{
    int i,j,k,x,y,z,m;
    long long sum=0;
    ifstream cin("traseu.in");
    ofstream cout("traseu.out");
    cin>>n>>m;
    for(i=1;i<=n;++i)
        for(j=1;j<=n;++j)
            if(i!=j) d[i][j]=INF;
    while(m--)
    {
        cin>>x>>y>>z;
        sum+=z;
        ++in[y]; ++out[x];
        d[x][y]=min(d[x][y],z);
    }

    for(k=1;k<=n;++k)
        for(i=1;i<=n;++i)
            for(j=1;j<=n;++j)
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);

    for(i=1;i<=n;++i)
    {
        if(in[i]>out[i]) v1[++l1]=i;
        if(in[i]<out[i]) v2[++l2]=i;
    }

    S=0; D=l1+l2+1;
    for(i=1;i<=l1;++i) add_edge(S,i,in[v1[i]]-out[v1[i]],0);
    for(i=1;i<=l1;++i)
        for(j=1;j<=l2;++j) add_edge(i,l1+j,INF,d[v1[i]][v2[j]]);
    for(i=1;i<=l2;++i) add_edge(l1+i,D,out[v2[i]]-in[v2[i]],0);

    cout<<sum+Min_Flow()<<"\n";
    return 0;
}