Cod sursa(job #744975)

Utilizator scipianusFMI Ciprian Olariu scipianus Data 10 mai 2012 11:27:26
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.94 kb
#include<fstream>
#include<vector>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,S,D;
int C[355][355],F[355][355],cost[355][355],Dist[355],viz[355],sum;
vector <int> G[355];
long long sol;
int H[355],poz[355],size;

inline int Min(int a,int b)
{
	if(a<b)
		return a;
	return b;
}

inline void Swap(int &a,int &b)
{
	if(a==b)
		return;
	a^=b^=a^=b;
}

inline void Citire()
{
	int i,x,y,cap,c,ns,poz,semn;
	char s[50];
	ifstream fin("fmcm.in");
	//fin>>n>>m>>S>>D;
	fin.getline(s,50);
	ns=strlen(s);
	poz=0;
	while(s[poz]!=' ')
	{
		n=n*10+s[poz]-'0';
		poz++;
	}
	poz++;
	while(s[poz]!=' ')
	{
		m=m*10+s[poz]-'0';
		poz++;
	}
	poz++;
	while(s[poz]!=' ')
	{
		S=S*10+s[poz]-'0';
		poz++;
	}
	poz++;
	while(poz<ns)
	{
		D=D*10+s[poz]-'0';
		poz++;
	}
	//
	for(i=1;i<=m;i++)
	{
		//fin>>x>>y>>cap>>c;
		fin.getline(s,50);
		ns=strlen(s);
		poz=0;
		x=0;
		if(s[poz]=='-')
		{
			semn=-1;
			poz++;
		}
		else
			semn=1;
		while(s[poz]!=' ')
		{
			x=x*10+s[poz]-'0';
			poz++;
		}
		x*=semn;
		poz++;
		y=0;
		if(s[poz]=='-')
		{
			semn=-1;
			poz++;
		}
		else
			semn=1;
		while(s[poz]!=' ')
		{
			y=y*10+s[poz]-'0';
			poz++;
		}
		y*=semn;
		poz++;
		cap=0;
		if(s[poz]=='-')
		{
			semn=-1;
			poz++;
		}
		else
			semn=1;
		while(s[poz]!=' ')
		{
			cap=cap*10+s[poz]-'0';
			poz++;
		}
		cap*=semn;
		poz++;
		c=0;
		if(s[poz]=='-')
		{
			semn=-1;
			poz++;
		}
		else
			semn=1;
		while(poz<ns)
		{
			c=c*10+s[poz]-'0';
			poz++;
		}
		c*=semn;
		//
		G[x].push_back(y);
		G[y].push_back(x);
		C[x][y]=cap;
		cost[x][y]=c;
		cost[y][x]=-c;
	}
	fin.close();
}

inline void Bellman_Ford()
{
	queue <int> Q;
	vector <int>::iterator it;
	int i,x;
	for(i=1;i<=n;i++)
		Dist[i]=2000000000;
	Dist[S]=0;
	Q.push(S);
	while(!Q.empty())
	{
		x=Q.front();
		Q.pop();
		for(it=G[x].begin();it!=G[x].end();it++)
		{
			if(C[x][*it]>0 && Dist[*it]>Dist[x]+cost[x][*it])
			{
				Dist[*it]=Dist[x]+cost[x][*it];
				Q.push(*it);
			}
		}
	}
	sum=Dist[D];
}

inline void Up_Heap(int nod)
{
	int tata=nod/2;
	while(tata>0 && Dist[H[nod]]<Dist[H[tata]])
	{
		Swap(H[nod],H[tata]);
		poz[H[nod]]=nod;
		poz[H[tata]]=tata;
		nod=tata;
		tata=nod/2;
	}
}

inline void Down_Heap(int nod)
{
	int tata=0;
	while(nod!=tata)
	{
		tata=nod;
		if(2*tata<=size && Dist[H[nod]]>Dist[H[2*tata]])
			nod=2*tata;
		if(2*tata+1<=size && Dist[H[nod]]>Dist[H[2*tata+1]])
			nod=2*tata+1;
		Swap(H[nod],H[tata]);
		poz[H[nod]]=nod;
		poz[H[tata]]=tata;
	}
}

inline bool Dijkstra()
{
	int i,x;
	vector <int>::iterator it;
	for(i=1;i<=n;i++)
	{
		if(Dist[i]==2000000000)
			continue;
		for(it=G[i].begin();it!=G[i].end();it++)
		{
			if(Dist[*it]==2000000000)
				continue;
			cost[i][*it]+=Dist[i]-Dist[*it];
		}
	}
	for(i=1;i<=n;i++)
	{
		Dist[i]=2000000000;
		viz[i]=0;
		H[i]=i;
		poz[i]=i;
	}
	Dist[S]=0;
	H[1]=S;	H[S]=1;
	poz[1]=S; poz[S]=1;
	size=n;
	while(size>1 && Dist[H[1]]!=2000000000)
	{
		x=H[1];
		H[1]=H[size]; poz[H[1]]=1;
		size--;
		if(size>1)
			Down_Heap(1);
		for(it=G[x].begin();it!=G[x].end();it++)
		{
			if(C[x][*it]>F[x][*it] && Dist[*it]>Dist[x]+cost[x][*it])
			{
				Dist[*it]=Dist[x]+cost[x][*it];
				viz[*it]=x;
				Up_Heap(poz[*it]);
			}
		}
	}
	if(Dist[D]==2000000000)
		return false;
	return true;
}

inline void Max_Flow()
{
	int x,val;
	while(1)
	{
		if(Dijkstra()==false)
			return;
		val=2000000000;
		x=D;
		while(viz[x])
		{
			val=Min(val,C[viz[x]][x]-F[viz[x]][x]);
			x=viz[x];
		}
		x=D;
		while(viz[x])
		{
			F[viz[x]][x]+=val;
			F[x][viz[x]]-=val;
			x=viz[x];
		}
		sum+=Dist[D];
		sol+=(long long)(val*sum);
	}
}

inline void Afisare()
{
	ofstream fout("fmcm.out");
	fout<<sol<<"\n";
	fout.close();
}

int main()
{
	Citire();
	Bellman_Ford();
	Max_Flow();
	Afisare();
	return 0;
}