Cod sursa(job #2592234)

Utilizator matei123Biciusca Matei matei123 Data 1 aprilie 2020 14:11:13
Problema Traseu Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.16 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;
}