Cod sursa(job #696572)

Utilizator giuliastefGiulia Stef giuliastef Data 28 februarie 2012 19:03:34
Problema Flux maxim de cost minim Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 3.14 kb
#include <cstdio>
#include <cstring>
#include <vector>
#define NMAX 357
#define INF 1<<30
using namespace std;
vector <int> G[NMAX];
int N,M,S,D,Sum,Drum,l;
int t[NMAX],c[NMAX][NMAX],cost[NMAX][NMAX],f[NMAX][NMAX],dist[NMAX],h[NMAX],pos[NMAX];
void Read(){
     int x,y,z,t;
     freopen("fmcm.in","r",stdin);
     scanf("%d%d%d%d",&N,&M,&S,&D);
     for(;M>0;M--){
      scanf("%d%d%d%d",&x,&y,&z,&t);
      G[x].push_back(y);
      G[y].push_back(x);
      c[x][y]=z;      
      cost[x][y]=t;
      cost[y][x]=-t;       
     }
}
void BellmanFord(){
     int i,j,stop;
     memset(dist,INF,sizeof(dist));
     dist[S]=0; stop=0;
     for(i=1;i<=N && !stop;i++){
       stop=1;
       for(j=1;j<=N;j++)
        for(vector<int>::iterator it=G[j].begin();it!=G[j].end();it++)
         if(c[j][*it]-f[j][*it]>0 && dist[j]+cost[j][*it]<dist[*it]){
                                  stop=0;
                                  dist[*it]=dist[j]+cost[j][*it];
         }
     }
     Sum=dist[D];
}
void upheap(int poz)
{
	int aux;
	while(poz>=1 && dist[h[poz]]<dist[h[poz/2]])
	{
		aux=pos[h[poz]];
		pos[h[poz]]=pos[h[poz/2]];
		pos[h[poz/2]]=aux;
		
		aux=h[poz];
		h[poz]=h[poz/2];
		h[poz/2]=aux;
		poz=poz/2;
	}
}
void downheap(int poz)
{
	int aux;
	while(poz*2+1<=l && (dist[h[poz]]>dist[h[poz*2]] || dist[h[poz]]>dist[h[poz*2+1]]))
	{
		if(poz*2+1<=l && dist[h[poz*2]]>dist[h[poz*2+1]])
		{
			aux=pos[h[poz]];
			pos[h[poz]]=pos[h[poz*2+1]];
			pos[h[poz*2+1]]=aux;
			
			aux=h[poz];
			h[poz]=h[poz*2+1];
			h[poz*2+1]=aux;
			poz=poz*2+1;
		}
		else
		{
			aux=pos[h[poz]];
			pos[h[poz]]=pos[h[poz*2]];
			pos[h[poz*2]]=aux;
			
			aux=h[poz];
			h[poz]=h[poz*2];
			h[poz*2]=aux;
			poz=poz*2;
		}
	}
}
int Dijkstra(){
    int i,nod;
    for(i=1;i<=N;i++)
     for(vector <int>::iterator it=G[i].begin();it!=G[i].end();it++)
      if(dist[i]!=INF && dist[*it]!=INF) cost[i][*it]+=dist[i]-dist[*it];
    memset(h,0,sizeof(h));
    memset(pos,-1,sizeof(pos));
    for(i=1;i<=N;i++){
     dist[i]=INF;
    }  
    l=1;
    dist[S]=0;
    h[l]=S;
    pos[S]=1;
    while(l){
     nod=h[1];
     h[1]=h[l--];
     pos[h[1]]=1;
     downheap(1);
     for(vector<int>::iterator it=G[nod].begin();it!=G[nod].end();it++){
      if(c[nod][*it]-f[nod][*it]>0 && dist[nod]+cost[nod][*it]<dist[*it]){
       dist[*it]=dist[nod]+cost[nod][*it];
       t[*it]=nod;
       if(pos[*it]==-1){
        h[++l]=*it;
        pos[h[l]]=l;
        upheap(pos[*it]);
       }
       else upheap(pos[*it]);
      }
     }
    }  
    if(dist[D]!=INF){
     int fmin=INF;
     Drum=1;
     for(i=D;i!=S;i=t[i])
      fmin=min(fmin,c[t[i]][i]-f[t[i]][i]);
     for(i=D;i!=S;i=t[i]){
      f[t[i]][i]+=fmin;
      f[i][t[i]]-=fmin;
     }
     Sum+=dist[D];
     return fmin*Sum;
    }
    return 0;
}
long long Flux(){
     long long Sol=0;
     Drum=1;
     while(Drum){
      Drum=0;
      Sol+=Dijkstra();
     }
     return Sol;
}
void Write(){
     freopen("fmcm.out","w",stdout);
     BellmanFord();
     printf("%lld\n",Flux());
}
int main(){
    Read();
    Write();
    return 0;
}