poj1459(網絡流)

昨天學的最高標號預流推進

  沒看別人代碼敲的,後來有一個BUG,參考了一下別人的代碼:http://www.cnblogs.com/Open_Source/archive/2010/08/03/1904898.html

能參考的資料太少了,基本上是連蒙帶猜寫的代碼,還好之前學過SAP,網絡流的算法原理好像都是基於最大流最小割定理的,組合數學上都有詳細的證明!

參考:

1.劉汝佳《算法藝術與信息學競賽》P321

2.http://trp.jlu.edu.cn/software/net/lssx/4/4.41.htm

總體感覺就像打乒乓球:推過去又送回來!

代碼:(注意越界!)

#include<cstdio>
#include<iostream>

using namespace std;
//   freopen("data.in","r",stdin);

#include<queue>
#include<cstring>
#define N 105
#define M (N*N+210)*2//double
#define INF 4000000000
int d[N];
struct cmp
{
    bool operator()(const int &u,const int &v)const
    {
        return d[u]<d[v];
    }
};
struct Node
{
    int u,v,next;
    int c;
};
struct Graph
{
    Node E[M];
    int first[N];
    int _V,_E,src,dest;
    __int64 rest[N];
    int in[N];
    priority_queue<int,vector<int>,cmp> active;
	
    void initial(int n)
    {
        _V=n+2;_E=0;
        src=n,dest=n+1;
        memset(first,-1,4*_V);//!!
    }
    void build(int n,int np,int nc,int m)
    {
        initial(n);
        int i,u,v,c;
        for(i=0; i<m; i++)
        {
            scanf("%*[^(](%d,%d)%d",&u,&v,&c);
            if(u==v)continue;
            add(u,v,c);
        }
        for(i=0; i<np; i++)
        {
            int u,c;
            scanf("%*[^(](%d)%d",&u,&c);
            add(src,u,c);
        }
        for(i=0; i<nc; i++)
        {
            int u,c;
            scanf("%*[^(](%d)%d",&u,&c);
            add(u,dest,c);
        }
    }
    void add(int u,int v,int c){
        E[_E].u=u,E[_E].v=v,E[_E].c=c,E[_E].next=first[u],first[u]=_E,_E++;
		E[_E].u=v,E[_E].v=u,E[_E].c=0,E[_E].next=first[v],first[v]=_E,_E++;//
    }
    void calHeight(){
        memset(d,-1,sizeof(d));
        d[dest]=0;
		int que[N],front,rear;
        front=rear=0;
        que[rear++]=dest;
        while(front!=rear){
            int v=que[front++],u;
            for(int e=first[v]; e!=-1; e=E[e].next){
                u=E[e].v;
                if(d[u]==-1){
                    d[u]=d[v]+1;
                    que[rear++]=u;
                }
            }
        }
        d[src]=_V;//!!
    }
	void preprocess(){
        for(int i=0;i<_V;i++)rest[i]=in[i]=0;
        rest[src]=INF;active.push(src);
    }
    inline void push(int u){
        for(int e=first[u]; e!=-1&&rest[u]; e=E[e].next){
			int v=E[e].v,c=E[e].c;
            if(d[E[e].v]+1==d[u]&&E[e].c){
				int aug=rest[u]<c?rest[u]:c;//!!
				rest[v]+=aug,rest[u]-=aug,E[e].c-=aug,E[e^1].c+=aug;
				if(!in[v]&&v!=dest&&v!=src){
					active.push(v);
					in[v]=true;
				}
			}
        }
	}
	inline bool relable(int u){
		d[u]=_V-1;
		for(int e=first[u]; e!=-1; e=E[e].next)if(E[e].c&&d[u]>d[E[e].v])d[u]=d[E[e].v];
		d[u]++;
		return d[u]!=_V;
	}
	__int64 preFlowPush()
	{
		calHeight();
		preprocess();
		while(!active.empty()){//!!不記錄s,t
			int u=active.top();
			push(u);//從點u進行推流
			if(rest[u]&&relable(u))continue;//可以繼續推流
			active.pop();in[u]=false;//否則彈出隊列
		}
		return rest[dest];
	}
	void display(){
		for(int i=0; i<_V; i++){
			for(int e=first[i]; e!=-1; e=E[e].next){
				int u=E[e].u,v=E[e].v,c=E[e].c;
				cout<<u<<' '<<v<<' '<<c<<endl;
			}
		}
	}
} net;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("data.in", "r", stdin);
#endif
	int n,np,nc,m;
	while(cin>>n)
	{
		cin>>np>>nc>>m;
		net.build(n,np,nc,m);
		//     net.display();
		printf("%I64d\n",net.preFlowPush());
	}
	return 0;
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章