Cod sursa(job #210789)

Utilizator bogdanhm999Casu-Pop Bogdan bogdanhm999 Data 29 septembrie 2008 12:57:12
Problema Cc Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.39 kb
#include <stdio.h>
#include <queue>
#define inf 1000000000
#define nMax 205
using namespace std;
long n,m,i,j,a,nod,minim,aux,flux;
long source, dest;
long cost[205][205], cap[205][205], t[205], path[205];
long d[nMax],g[nMax],v[nMax][nMax/2],ctotal;
bool iq[nMax];

void bellman(){
    queue<int>Q;
    for (i=1;i<=dest;++i){d[i]=inf;t[i]=0;iq[i]=0;} d[source]=0;
    while(!Q.empty())Q.pop();
    Q.push(source);iq[source]=1;
    while (!Q.empty()){
          nod=Q.front(); Q.pop();
          iq[nod]=0;
          for (i=0;i<g[nod];++i)
             if (cap[nod][v[nod][i]])
              if (d[nod]+cost[nod][v[nod][i]] < d[v[nod][i]]){
                 d[v[nod][i]]=d[nod]+cost[nod][v[nod][i]];
                 t[v[nod][i]]=nod;
                 if (!iq[v[nod][i]]){
                    Q.push(v[nod][i]);
                    iq[v[nod][i]]=1;
                 }
              }
    }
}

void ed(){
     bellman();
     m=0;aux=dest;
     while (aux!=0){ path[++m] = aux ; aux=t[aux] ; }
}

int main(){
    freopen("cc.in","r",stdin);
    freopen("cc.out","w",stdout);
    scanf("%ld",&n);
    for (i=1;i<=n;++i)
        for (j=1;j<=n;++j){
            scanf("%ld",&a); cost[i][n+j]=a; cost[n+j][i]=-a; cap[i][n+j]=1; }
    source=n+n+1;dest=source+1;
    //nodul 2n+1 si 2n+2 noduri sursa respectiv destinatie
    for (i=1;i<=n;++i){ cap[source][i]=1; cap[n+i][dest]=1;}
    //generam listele de adiacenta pt bellman-ford
    for (i=1;i<=n;++i){
        for (j=0;j<n;++j){
            v[i][j]=n+j+1;// legatura intre 1,2,3,..,n si n+1,n+2,..,n+n
            v[n+i][j]=j+1;//legatura intre n+1,n+2,..,n+n si 1,2,3,..,n
        }
        v[i][n]=source;  //legatura intre 1,2,3,..,n si sursa
        v[source][i-1]=i;//legatura intre sursa si 1,2,3,..,n
        v[n+i][n]=dest;  //legatura intre n+1,n+2,..,n+n si dest
        v[dest][i-1]=n+i;//legatura intre dest si n+1,n+2,..,n+n
        g[i]=n+1;
        g[n+i]=n+1;
    }
    g[dest]=n;
    g[source]=n;
    ///////////////////////////////////////////
    flux=0;
    do{
       ed(); if (m<4)break;
       minim=inf;
       for (i=1;i<m;++i)
           if (cap[path[i+1]][path[i]] < minim) minim = cap[path[i+1]][path[i]];
       for (i=1;i<m;++i){cap[path[i+1]][path[i]]-=minim; cap[path[i]][path[i+1]]+=minim;}
       flux+=minim;
       ctotal+=d[dest];
    }while(m);
    printf("%ld\n",ctotal);
return 0;
}