poj1149(pigs)

一、.这么犀利的建图第一次见到,不解释。就用这个题写一下模板。

参考资料:http://imlazy.ycool.com/post.2059102.html

二、代码

1.(dinic+邻接表)

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
//注意数据和内存的越界!
//尤其是memset()上
#define N 1010
#define M 11000//double
#define INF 100000000
int idx[N],cnt[N];
struct Node{
    int u,v,next;
    int c;
};
struct Graph
{
    Node E[M];
    int first[N];
    int _V,_E,src,dest;
    int que[N],front,rear;
	int d[N];
    void init(int n){
        _V=n,_E=0;
		src=0;dest=_V-1;
        memset(first,-1,4*_V);//!!!
    }
   void build(int house,int cust)
    {
		init(cust+2);
		int i,j;
		for(i=1;i<=house;i++)
		{
			idx[i]=-1;
			scanf("%d",cnt+i);
		}
		
		int loop,num,cap;
		for(i=1;i<=cust;i++)
		{
			cap=0;
			scanf("%d",&num);
			for(j=0;j<num;j++)
			{
				scanf("%d",&loop);
				if(idx[loop]!=-1)add(idx[loop],i,INF);
				else cap+=cnt[loop],idx[loop]=i;
			}
			if(cap)add(src,i,cap);

			scanf("%d",&num);
			add(i,dest,num);
		}
	}
    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++;//
    }
	bool bfs()
	{
		memset(d,-1,4*_V);//!!!
		d[src]=0;
		front=rear=0;
		que[rear++]=src;
		while(front!=rear){
			int u=que[front++];
			for(int e=first[u];e!=-1;e=E[e].next){
				int v=E[e].v;
				if(d[v]==-1&&E[e].c){
					d[v]=d[u]+1;
					que[rear++]=v;
				}
				if(d[dest]!=-1)return true;
			}
		}
		return false;
	}
	int dfs(int u,int cap)
	{
		if(u==dest)return cap;
		int rest=cap,aug;
		for(int e=first[u];e!=-1&&rest;e=E[e].next){//
			int v=E[e].v,c=E[e].c;
			if(d[v]==d[u]+1&&c){
				aug=dfs(v,rest>c?c:rest);
				rest-=aug;
				E[e].c-=aug;
				E[e^1].c+=aug;
			}
		}
		return cap-rest;
	}
	int dinic(){
		int flow=0;
		while(bfs())flow+=dfs(src,INF);
		return flow;
	}
	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;
				int c=E[e].c;
                cout<<u<<' '<<v<<' ';
				printf("%d\n",c);
            }
        }
    }
}net;

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("data.in", "r", stdin);
    #endif

    int n,m;
    cin>>n>>m;
    net.build(n,m);
   // net.display();
    printf("%d\n",net.dinic());
    return 0;
}


三、dinic+邻接阵
#include <iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;

#define N 1010
#define INF 100000000

int idx[N];
int cnt[N];

struct Graph{
	int map[N][N];
	int _V,src,dest;
	int que[N],front,rear;
	int d[N];
	void init(int n)
    {
        _V=n;
		src=0;dest=_V-1;
		for(int i=0;i<_V;i++)
			for(int j=0;j<_V;j++)map[i][j]=0;//!!
    }
	void build(int house,int cust)
	{
		init(cust+2);
		
		int i,j;
		for(i=1;i<=house;i++)
		{
			idx[i]=-1;
			scanf("%d",cnt+i);
		}
		
		int loop,num,cap;
		for(i=1;i<=cust;i++)
		{
			cap=0;
			scanf("%d",&num);
			for(j=0;j<num;j++)
			{
				scanf("%d",&loop);
				if(idx[loop]!=-1)map[idx[loop]][i]=INF;
				else cap+=cnt[loop],idx[loop]=i;
			}
			if(cap)
				map[src][i]=cap;
			scanf("%d",&num);
			map[i][dest]=num;
		}
	}
	bool bfs(){
		memset(d,-1,4*_V);//!!!
		d[src]=0;
		front=rear=0;
		que[rear++]=src;
		while(front!=rear){
			int u=que[front++];
			for(int v=0;v<_V;v++){
				if(d[v]==-1&&map[u][v]){
					d[v]=d[u]+1;
					que[rear++]=v;
				}
				if(d[dest]!=-1)return true;//
			}
		}
		return false;
	}
	//函数的意义:求从u增广的最大流量,cp:当前可增广的最大流
	int dfs(int u,int cap){
		if(u==dest)return cap;
		int rest=cap,aug;
		for(int v=0;v<_V&&rest;v++){
			if(d[v]==d[u]+1&&map[u][v]>0){
				aug=dfs(v,rest<map[u][v]?rest:map[u][v]);
				rest-=aug;
				map[u][v]-=aug;
				map[v][u]+=aug;
			}
		}
		return cap-rest;
	}
	int dinic(){
		int flow=0;
		while(bfs())flow+=dfs(src,INF);
		return flow;
	}
	void display()
	{
		for(int i=0;i<_V;i++)
			for(int j=0;j<_V;j++)cout<<i<<' '<<j<<' '<<map[i][j]<<endl;
		cout<<endl;
	}
}net;

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


四、sap(邻接表)

一直都觉得从后往前标记不习惯,于是打算打算写从前往后标记的,但后来发现行不通!

才明白从后往前标记是没办法的办法呀!

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;

//注意数据和内存的越界!
//尤其是memset()上
#define N 1010
#define M 11000//double
#define INF 100000000
int idx[N],cnt[N];
struct Node{
    int u,v,next;
    int c;
};
struct Graph
{
    Node E[M];
    int first[N];
    int _V,_E,src,dest;
	int d[N];
	int num[N];
	int pre[N],cur,next;
	
    void init(int n){
        _V=n,_E=0;
		src=0;dest=_V-1;
        memset(first,-1,4*_V);//!!!
    }
	void build(int house,int cust)
    {
		init(cust+2);
		int i,j;
		for(i=1;i<=house;i++)
		{
			idx[i]=-1;
			scanf("%d",cnt+i);
		}
		
		int loop,num,cap;
		for(i=1;i<=cust;i++)
		{
			cap=0;
			scanf("%d",&num);
			for(j=0;j<num;j++)
			{
				scanf("%d",&loop);
				if(idx[loop]!=-1)add(idx[loop],i,INF);
				else cap+=cnt[loop],idx[loop]=i;
			}
			if(cap)add(src,i,cap);
			
			scanf("%d",&num);
			add(i,dest,num);
		}
	}
    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++;//
    }
	inline bool advance(){
		for(int e=first[cur];e!=-1;e=E[e].next){
			if(d[cur]==d[E[e].v]+1&&E[e].c){
				pre[cur=E[e].v]=e;
				return true;
			}
		}
		return false;
	}
	inline int relable(){
		int mini=_V-1;
		for(int e=first[cur];e!=-1;e=E[e].next)if(E[e].c&&d[E[e].v]<mini)mini=d[E[e].v];
		return mini+1;
	}
	int sap(){
		memset(d,-1,4*_V);//!!!
		memset(num,0,4*_V);//
		pre[src]=-1;//!!!
		int flow=0,aug;

		while(d[src]!=_V){
			cur=src;
			while(cur!=dest){
				if(advance())continue;
				int lable=relable();
				num[d[cur]]--;num[d[cur]=lable]++;
				if( !num[d[cur]] || d[src]==_V )return flow;	
				if(cur!=src)cur=E[pre[cur]].u;//满足可行弧定义
			}
			aug=INF;
			int e=pre[dest],aug=INF;
			while(e!=-1)aug=aug<E[e].c?aug:E[e].c,e=pre[E[e].u];
			flow+=aug;e=pre[dest];
			while(e!=-1)E[e].c-=aug,E[e^1].c+=aug,e=pre[E[e].u];
		}
		return flow;
	}	
}net;

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





4.sap+邻接阵

#include <iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;

#define N 1010
#define INF 100000000

int idx[N];
int cnt[N];

struct Graph{
	int map[N][N];
	int _V,src,dest;
	int d[N];
	int num[N];
	int pre[N];
	void init(int n){
        _V=n;
		src=0;dest=_V-1;
		for(int i=0;i<_V;i++)
			for(int j=0;j<_V;j++)map[i][j]=0;//!!
    }
	void build(int house,int cust)
	{
		init(cust+2);
		
		int i,j;
		for(i=1;i<=house;i++)
		{
			idx[i]=-1;
			scanf("%d",cnt+i);
		}
		
		int loop,num,cap;
		for(i=1;i<=cust;i++)
		{
			cap=0;
			scanf("%d",&num);
			for(j=0;j<num;j++)
			{
				scanf("%d",&loop);
				if(idx[loop]!=-1)map[idx[loop]][i]=INF;
				else cap+=cnt[loop],idx[loop]=i;
			}
			if(cap)
				map[src][i]=cap;
			scanf("%d",&num);
			map[i][dest]=num;
		}
	}
   inline bool  advance(int &u){
		for(int v=0;v<_V;v++){
			if(d[u]==d[v]+1&&map[u][v]){
				pre[v]=u;u=v;
				return true;
			}
		}
		return false;
	}

	inline int relable(int u){
		int mini=_V-1;
		for(int v=0;v<_V;v++)
			if(map[u][v]&&d[v]<mini)
				mini=d[v];
		return mini+1;
	}
	int sap(){
		int u,v,flow=0;
		memset(d,-1,4*_V);//bfs();
		memset(num,0,4*_V);pre[src]=-1;
		
		while(true){
			u=src;
			while(u!=dest){
				if(advance(u))continue;
				int lable=relable(u);
				num[d[u]]--;num[d[u]=lable]++;
				if( !num[d[u]] || d[src]==_V )return flow;
				//!!源点标号不成功时,断层时到达最大流	
				if(u!=src)u=pre[u];
			}
			v=u,u=pre[v];int aug=INF;
			while(u!=-1)aug=aug<map[u][v]?aug:map[u][v],v=u,u=pre[u];
			flow+=aug;v=dest,u=pre[v];
			while(u!=-1)map[u][v]-=aug,map[v][u]+=aug,v=u,u=pre[u];
		}
	return flow;
	}
	void display()
	{
		for(int i=0;i<_V;i++)
			for(int j=0;j<_V;j++)cout<<i<<' '<<j<<' '<<map[i][j]<<endl;
			cout<<endl;
	}
}net;

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



我始终都没搞懂为什么sap用bfs()预处理就会WA,用memset(d,-1,4*_V)就不会!贴下bfs()的代码。。。


void bfs(){
		memset(d,-1,4*_V);//!!!
		num[d[dest]=0]++;
		int que[N],front,rear;
		front=rear=0;
		que[rear++]=dest;
		while(front!=rear){
			int v=que[front++];
			for(int u=0;u<_V;u++){
				if(d[u]==-1&&map[u][v]){
					num[d[u]=d[v]+1]++;
					que[rear++]=u;
				}
			}
		}
	}

5.高标预流推进(邻接表)

#include<cstdio>
#include<iostream>

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

#include<queue>
#include<cstring>
#define N 1010
#define M 11000//double
#define INF 100000000
int idx[N],cnt[N];
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 init(int n){
        _V=n,_E=0;
		src=0;dest=_V-1;
        memset(first,-1,4*_V);//!!!
    }
   void build(int house,int cust){
		init(cust+2);
		int i,j;
		for(i=1;i<=house;i++)
		{
			idx[i]=-1;
			scanf("%d",cnt+i);
		}
		
		int loop,num,cap;
		for(i=1;i<=cust;i++)
		{
			cap=0;
			scanf("%d",&num);
			for(j=0;j<num;j++)
			{
				scanf("%d",&loop);
				if(idx[loop]!=-1)add(idx[loop],i,INF);
				else cap+=cnt[loop],idx[loop]=i;
			}
			if(cap)add(src,i,cap);

			scanf("%d",&num);
			add(i,dest,num);
		}
	}
    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;
                }
            }
        }
    }
	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,m;
    cin>>n>>m;
    net.build(n,m);
   // net.display();
    printf("%d\n",net.preFlowPush());
    return 0;
}


6.高标预流推进(邻接阵)

#include<cstdio>
#include<iostream>

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

#include<queue>
#include<cstring>
#define N 1010
#define M 11000//double
#define INF 100000000
int d[N];
struct cmp{
    bool operator()(const int &u,const int &v)const{
        return d[u]<d[v];
    }
};

int idx[N];
int cnt[N];

struct Graph{
	int map[N][N];
    int _V,_E,src,dest;
    __int64 rest[N];
    int in[N];
    priority_queue<int,vector<int>,cmp> active;
	void init(int n)
    {
        _V=n;
		src=0;dest=_V-1;
		for(int i=0;i<_V;i++)
			for(int j=0;j<_V;j++)map[i][j]=0;//!!
    }
	void build(int house,int cust)
	{
		init(cust+2);
		
		int i,j;
		for(i=1;i<=house;i++)
		{
			idx[i]=-1;
			scanf("%d",cnt+i);
		}
		
		int loop,num,cap;
		for(i=1;i<=cust;i++)
		{
			cap=0;
			scanf("%d",&num);
			for(j=0;j<num;j++)
			{
				scanf("%d",&loop);
				if(idx[loop]!=-1)map[idx[loop]][i]=INF;
				else cap+=cnt[loop],idx[loop]=i;
			}
			if(cap)
				map[src][i]=cap;
			scanf("%d",&num);
			map[i][dest]=num;
		}
	}
    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++];
            for(int u=0;u<_V;u++){
                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 v=0;v<_V&&rest[u];v++){
            if(d[v]+1==d[u]&&map[u][v]){
				int aug=rest[u]<map[u][v]?rest[u]:map[u][v];//!!
				rest[v]+=aug,rest[u]-=aug,map[u][v]-=aug,map[v][u]+=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 v=0;v<_V;v++)if(map[u][v]&&d[u]>d[v])d[u]=d[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 j=0;j<_V;j++)cout<<i<<' '<<j<<' '<<map[i][j]<<endl;
		cout<<endl;
	}
} net;

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("data.in", "r", stdin);
    #endif

    int n,m;
    cin>>n>>m;
    net.build(n,m);
   // net.display();
    printf("%d\n",net.preFlowPush());
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值