Cod sursa(job #1464995)

Utilizator TeodorescuStefanEduardTeodorescu Stefan Eduard TeodorescuStefanEduard Data 26 iulie 2015 11:40:40
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.84 kb
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define pb push_back
#define maxn 650
#define inf 0x3f3f3f3f
 
using namespace std;
 
int n , nL , nR , m , nh , flow , flowcost , source , sink ;
int h[maxn] , pos[maxn] , d[maxn] , oldd[maxn] , reald[maxn] ,father[maxn] , mch[maxn][maxn] ;
int cap[maxn][maxn] , f[maxn][maxn], cost[maxn][maxn] ;
bool inside[maxn] ;
vector <int> l[maxn] ;
 
void read()
{
    int x , y , cst ;
    scanf ( "%d%d%d" , &nL ,&nR , &m ) ;
    source = 1 ;
    for ( int i = 1 ; i <= m ; ++ i )
    {
        scanf ( "%d%d%d" , &x , &y , &cst ) ;
        ++ x ;
        y += nL + 1 ;
        l[x].pb(y) ;
        l[y].pb(x) ;
        cap[x][y] = 1 ;
        cost[x][y] = cst ;
        cost[y][x] = -cst ;
        mch[x][y] = i ;
    }
 
    for ( int i = 2 ; i <= nL + 1 ; ++ i )
    {
        l[source].pb(i) ;
        l[i].pb(source) ;
        cap[source][i] = 1 ;
    }
 
    n = nL + nR + 2 ;
    sink = n ;
 
    for ( int i = nL + 2 ;i < n ; ++ i )
    {
        l[i].pb(sink) ;
        l[sink].pb(i) ;
        cap[i][sink] = 1 ;
    }
}
 
void bellman()
{
    int k;
    queue <int> q;
 
    memset(oldd,inf,sizeof(oldd)) ;
    oldd[source] = 0 ;
 
    for ( q.push(source) , inside[source]=true ; !q.empty() ; q.pop() , inside[k] = false )
    {
        k = q.front() ;
        for ( unsigned int i = 0 ; i < l[k].size() ; ++ i )
         if ( cap[k][l[k][i]] && oldd[k] + cost[k][l[k][i]] < oldd[l[k][i]] )
         {
             oldd[l[k][i]] = oldd[k] + cost[k][l[k][i]] ;
             if ( !inside[l[k][i]] )
             {
                 q.push(l[k][i]) ;
                 inside[l[k][i]] = true ;
             }
         }
    }
}
 
void swap ( int i , int j )
{
    int aux ;
    aux = h[i] ; h[i] = h[j] ; h[j] = aux ;
    pos[h[i]] = i ; pos[h[j]] = j ;
}
 
void heap_up(int k)
{
    if( k <= 1 )
         return;
    int i = k >> 1 ;
    if( d[h[k]]<d[h[i]] ) { swap(i,k) ; heap_up(i) ; }
}
 
void heap_dw(int k)
{
    int i = k << 1 ;
    if ( i <= nh )
    {
        if ( i + 1 <= nh && d[h[i+1]]<d[h[i]]) ++ i ;
        if( d[h[i]] < d[h[k]] ) { swap(i,k) ; heap_dw(i) ; }
    }
}
 
int extract()
{
    swap ( 1 , nh ) ;
    -- nh ;
    pos [h[nh+1]] = 0 ;
    return h[nh+1] ;
}
 
int dijkstra()
{
    int k , newcost ;
    for ( int i = 1 ;i <= n ;++ i ) { h[i] = i ; pos[i] = i ; d[i] = inf ; father[i] = 0 ; }
    d[source] = reald[source] = 0 ;
    nh = n;
 
    while ( nh > 0 )
    {
        k = extract() ;
        heap_dw(1) ;
 
        for ( unsigned int i = 0 ; i <l[k].size() ; ++ i )
         if ( pos[l[k][i]] && f[k][l[k][i]] < cap[k][l[k][i]] )
         {
             newcost = d[k] + cost[k][l[k][i]] + oldd[k] - oldd[l[k][i]] ;
             if ( newcost < d[l[k][i]] )
             {
                 d[l[k][i]] = newcost ;
                 reald[l[k][i]] = reald[k] + cost[k][l[k][i]] ;
                 father[l[k][i]] = k ;
                 heap_up( pos[l[k][i]]) ;
             }
 
         }
    }
    memcpy( oldd , reald , sizeof(reald)) ;
    if ( d[sink] == inf ) return 0 ;
    return 1 ;
}
 
void update()
{
    int i ;
    for ( i = sink ; father[i] ; i = father[i] )
    {
        ++ f[father[i]][i] ;
        -- f[i][father[i]] ;
    }
    ++ flow ;
    flowcost += reald[sink] ;
}
 
void print()
{
    printf ( "%d %d\n" , flow , flowcost ) ;
    for ( int i = 2 ; i <= nL + 1 ; ++ i )
     for ( int j = nL + 2 ; j < n ; ++ j )
        if( f[i][j] )
            printf("%d ",mch[i][j]) ;
}
 
int main()
{
    freopen ( "cmcm.in" , "r" , stdin ) ;
    freopen ( "cmcm.out" , "w" , stdout ) ;
 
    read() ;
    bellman() ;
    while(dijkstra()) update() ;
    print() ;
 
    fclose(stdin) ;
    fclose(stdout) ;
    return 0;
}