HDU 4292 Food 网络流模板

http://acm.hdu.edu.cn/showproblem.php?pid=4292

题解:网络流模板题

之前用的dinic模板加弧优化(不优化TLE)居然还不如kuangbin模板不优化快,网上找了另一个dinic不用队列快的更多

代码:

kuangbin

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1000;//点数的最大值
const int MAXM=1000500;//边数的最大值

struct Node
{
    int from,to,next;
    int cap;
}edge[MAXM];
int tol;

int dep[MAXN];//dep为点的层次
int head[MAXN];

int n;
void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)//第一条变下标必须为偶数
{
    edge[tol].from=u;
    edge[tol].to=v;
    edge[tol].cap=w;
    edge[tol].next=head[u];
    head[u]=tol++;
    edge[tol].from=v;
    edge[tol].to=u;
    edge[tol].cap=0;
    edge[tol].next=head[v];
    head[v]=tol++;
}

int BFS(int start,int end)
{
    int que[MAXN];
    int front,rear;
    front=rear=0;
    memset(dep,-1,sizeof(dep));
    que[rear++]=start;
    dep[start]=0;
    while(front!=rear)
    {
        int u=que[front++];
        if(front==MAXN)front=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].cap>0&&dep[v]==-1)
            {
                dep[v]=dep[u]+1;
                que[rear++]=v;
                if(rear>=MAXN)rear=0;
                if(v==end)return 1;
            }
        }
    }
    return 0;
}
int dinic(int start,int end)
{
    int res=0;
    int top;
    int stack[MAXN];//stack为栈,存储当前增广路
    int cur[MAXN];//存储当前点的后继
    while(BFS(start,end))
    {
        memcpy(cur,head,sizeof(head));
        int u=start;
        top=0;
        while(1)
        {
            if(u==end)
            {
                int min=INF;
                int loc;
                for(int i=0;i<top;i++)
                  if(min>edge[stack[i]].cap)
                  {
                      min=edge[stack[i]].cap;
                      loc=i;
                  }
                for(int i=0;i<top;i++)
                {
                    edge[stack[i]].cap-=min;
                    edge[stack[i]^1].cap+=min;
                }
                res+=min;
                top=loc;
                u=edge[stack[top]].from;
            }
            for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
              if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
                 break;
            if(cur[u]!=-1)
            {
                stack[top++]=cur[u];
                u=edge[cur[u]].to;
            }
            else
            {
                if(top==0)break;
                dep[u]=-1;
                u=edge[stack[--top]].from;
            }
        }
    }
    return res;
}

int food[MAXN],drink[MAXM];
char ch;
int main()
{
	int nn,f,d;
	int i,j;
	while(~scanf("%d%d%d",&nn,&f,&d)){
		n=2*nn+f+d+2;
		init();
		for(i=1;i<=f;i++)scanf("%d",&food[i]);
		for(i=1;i<=d;i++)scanf("%d",&drink[i]);
		getchar();
		for(i=1;i<=nn;i++){
			for(j=1;j<=f;j++){
				scanf("%c",&ch);
				if(ch=='Y'){
					addedge(j,f+i,1);
				}
			}
			getchar();
		}
		for(i=1;i<=nn;i++){
			for(j=1;j<=d;j++){
				scanf("%c",&ch);
				if(ch=='Y')addedge(f+nn+i,2*nn+f+j,1);
			}
			getchar();
		}
		for(i=1;i<=nn;i++)addedge(f+i,nn+f+i,1);
		for(i=1;i<=f;i++)addedge(2*nn+f+d+1,i,food[i]);
		for(i=1;i<=d;i++)addedge(2*nn+f+i,2*nn+f+d+2,drink[i]);
		printf("%d\n",dinic(2*nn+f+d+1,2*nn+f+d+2));
	}
  //  cout << "Hello world!" << endl;
    return 0;
}

原模版

#include <iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxN=1000;
const int maxM=1000000;
const int inf=0x3f3f3f3f;
class Graph
{
private:
    int cnt;
    int Head[maxN];
    int Next[maxM];
    int W[maxM];
    int V[maxM];
    int Depth[maxN];
    int cur[maxN];//cur就是记录当前点u循环到了哪一条边
public:
    int s,t,n;
   void init(int nn,int ss,int tt)//初始化
        {
            n=nn;
            s=ss;
            t=tt;
            cnt=-1;
            memset(Head,-1,sizeof(Head));
            memset(Next,-1,sizeof(Next));
            return;
        }
    void _Add(int u,int v,int w)
        {
            cnt++;
            Next[cnt]=Head[u];
            Head[u]=cnt;
            V[cnt]=v;
            W[cnt]=w;
        }
    void Add_Edge(int u,int v,int w)
        {
            _Add(u,v,w);
            _Add(v,u,0);
        }
    int dfs(int u,int flow)
        {
            if (u==t)
                return flow;
            for (int& i=cur[u];i!=-1;i=Next[i])//注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
            {
                if ((Depth[V[i]]==Depth[u]+1)&&(W[i]!=0))
                {
                    int di=dfs(V[i],min(flow,W[i]));
                    if (di>0)
                    {
                        W[i]-=di;
                        W[i^1]+=di;
                        return di;
                    }
                }
            }
            return 0;
        }
    int bfs()
        {
            queue<int> Q;
            while (!Q.empty())
                Q.pop();
            memset(Depth,0,sizeof(Depth));
            Depth[s]=1;
            Q.push(s);
            do
            {
                int u=Q.front();
                Q.pop();
                for (int i=Head[u];i!=-1;i=Next[i])
                    if ((Depth[V[i]]==0)&&(W[i]>0))
                    {
                        Depth[V[i]]=Depth[u]+1;
                        Q.push(V[i]);
                    }
            }
            while (!Q.empty());
            if (Depth[t]>0)
                return 1;
            return 0;
        }
    int Dinic()
        {
            int Ans=0;
            while (bfs())
            {
                for (int i=1;i<=n;i++)//每一次建立完分层图后都要把cur置为每一个点的第一条边 感谢@青衫白叙指出这里之前的一个疏漏
                    cur[i]=Head[i];
                while (int d=dfs(s,inf))
                {
                    Ans+=d;
                }
            }
            return Ans;
        }
};
int food[maxN],drink[maxN];
char ch;
int main()
{
	int n,f,d;
	int i,j;
	Graph G;
	while(~scanf("%d%d%d",&n,&f,&d)){
		G.init(2*n+f+d+2,2*n+f+d+1,2*n+f+d+2);
		for(i=1;i<=f;i++)scanf("%d",&food[i]);
		for(i=1;i<=d;i++)scanf("%d",&drink[i]);
		getchar();
		for(i=1;i<=n;i++){
			for(j=1;j<=f;j++){
				scanf("%c",&ch);
				if(ch=='Y'){
					G.Add_Edge(j,f+i,1);
				}
			}
			getchar();
		}
		for(i=1;i<=n;i++){
			for(j=1;j<=d;j++){
				scanf("%c",&ch);
				if(ch=='Y')G.Add_Edge(f+n+i,2*n+f+j,1);
			}
			getchar();
		}
		for(i=1;i<=n;i++)G.Add_Edge(f+i,n+f+i,1);
		for(i=1;i<=f;i++)G.Add_Edge(2*n+f+d+1,i,food[i]);
		for(i=1;i<=d;i++)G.Add_Edge(2*n+f+i,2*n+f+d+2,drink[i]);
		printf("%d\n",G.Dinic());
	}
  //  cout << "Hello world!" << endl;
    return 0;
}

最快的

#include<cstdio>
#include<cstring>
using namespace std;
const int inf=1<<30;
const int nMax=100105;
const int mMax=3000005;
struct Node
{
	int c,u,v,next;
	void insert(int nu,int nv,int nc,int nnext)
	{
		u=nu;
		v=nv;
		c=nc;
		next=nnext;
	}
}edge[mMax];
int ne,head[nMax];
int cur[nMax],ps[nMax],dep[nMax];
 
void addedge(int u,int v,int w) //加边
{
	edge[ne].insert(u,v,w,head[u]);
	head[u]=ne++;
	edge[ne].insert(v,u,0,head[v]);
	head[v]=ne++;
}
 
int dinic(int s, int t){                       //  dinic
    int tr, res = 0;
    int i, j, k, f, r, top;
    while(1){
        memset(dep, -1, sizeof(dep));
        for(f = dep[ps[0]=s] = 0, r = 1; f != r;)
        {
            for(i = ps[f ++], j = head[i]; j; j = edge[j].next)
            {
                if(edge[j].c && dep[k=edge[j].v] == -1)
                {
                    dep[k] = dep[i] + 1;
                    ps[r ++] = k;
                    if(k == t)
                    {
                        f = r; break;
                    }
                }
            }
        }
        if(dep[t] == -1) break;
        memcpy(cur, head, sizeof(cur));
        i = s, top = 0;
        while(1)
        {
            if(i == t)
            {
                for(tr =inf, k = 0; k < top; k ++)
                {
                    if(edge[ps[k]].c < tr)
                    {
                        tr = edge[ps[f=k]].c;
                    }
                }
                for(k = 0; k < top; k ++)
                {
                    edge[ps[k]].c -= tr;
                    edge[ps[k]^1].c += tr;
                }
                i = edge[ps[top=f]].u;
                res += tr;
            }
            for(j = cur[i]; cur[i]; j = cur[i] =edge[cur[i]].next)
            {
                if(edge[j].c && dep[i]+1 == dep[edge[j].v])
                {
                	break;
                }
            }
            if(cur[i])
            {
                ps[top ++] = cur[i];
                i = edge[cur[i]].v;
            }
            else
            {
                if(top == 0)
                {
                	break;
                }
                dep[i] = -1;
                i = edge[ps[-- top]].u;
            }
        }
    }
    return res;
}
 
int main()
{
	int i,j,a,b,s,t,f,n,d;
	char str[205];
	while(~scanf("%d%d%d",&n,&f,&d))
	{
		s=0;
		t=f+n+d+10+n;
		ne=2;
		memset(head,0,sizeof(head));
		for(i=1;i<=f;i++)
		{
			scanf("%d",&a);
			addedge(s,i,a);
		}
		for(i=1;i<=d;i++)
		{
			scanf("%d",&a);
			addedge(f+n+n+i,t,a);
		}
 
		for(i=1;i<=n;i++)
		{
			addedge(f+i,f+n+i,1);
		}
 
		for(i=1;i<=n;i++)
		{
			scanf("%s",str);
			for(j=1;j<=f;j++)
			{
				if(str[j-1]=='Y')
				{
					addedge(j,f+i,inf);
				}
			}
		}
		for(i=1;i<=n;i++)
		{
			scanf("%s",str);
			for(j=1;j<=d;j++)
			{
				if(str[j-1]=='Y')
				{
					addedge(f+n+i,f+n+n+j,inf);
				}
			}
		}
		printf("%d\n",dinic(s,t));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/nwpu2017300135/article/details/81462095