zoukankan      html  css  js  c++  java
  • 洛谷.2754.星际转移问题(最大流Dinic 分层)

    题目链接

    枚举时间
    每一个时间点 对于每个之前的位置像当前位置连边,表示这一时刻可待在原地
    每艘船 之前时刻位置向当前时刻连边
    注意别漏了0时刻src连向earth的边

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #define gc() getchar()
    const int T=501,N=17*T,M=25*T,INF=1e7;
    
    int n,m,k,src,des,v[25],num[25],pos[25][20];
    int Enum,H[N],nxt[M<<1],to[M<<1],cap[M<<1],q[N],lev[N],cur[N];
    
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now*f;
    }
    inline void AddEdge(int u,int v,int w)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], cap[Enum]=w, H[u]=Enum;
    	to[++Enum]=u, nxt[Enum]=H[v], cap[Enum]=0, H[v]=Enum;
    }
    bool BFS(int mx)//这个上界别搞错。。
    {
    	for(int i=0;i<=mx;++i) lev[i]=0,cur[i]=H[i];
    	lev[des]=0;//, cur[des]=H[des];
    	lev[src]=1, q[0]=src;
    	int h=0,t=1;
    	while(h<t)
    	{
    		int x=q[h++];
    		for(int i=H[x];i;i=nxt[i])
    			if(!lev[to[i]] && cap[i])
    			{
    				lev[to[i]]=lev[x]+1, q[t++]=to[i];
    				if(to[i]==des) return 1;
    			}
    	}
    	return 0;
    }
    int Dinic(int u,int flow)
    {
    	if(u==des) return flow;
    	int used=0;
    	for(int &i=cur[u];i;i=nxt[i])
    		if(lev[to[i]]==lev[u]+1 && cap[i])
    		{
    			int delta=Dinic(to[i],std::min(cap[i],flow-used));
    			if(delta)
    			{
    				cap[i]-=delta, cap[i^1]+=delta, used+=delta;
    				if(used==flow) return flow;
    			}
    		}
    	lev[u]=0;
    	return used;
    }
    
    int main()
    {
    	n=read()+2,m=read(),k=read();
    	Enum=1, src=0, des=7501;
    	for(int i=1;i<=m;++i)
    	{
    		v[i]=read(), num[i]=read();
    		for(int j=0;j<num[i];++j)
    		{
    			pos[i][j]=read();
    			if(!pos[i][j]) pos[i][j]=n-1;
    			else if(pos[i][j]==-1) pos[i][j]=n;
    		}
    	}
    	int res=0,tot=0;
    	AddEdge(src,n-1,INF);//,AddEdge(n,des,INF);
    	while(++res<500)
    	{
    		AddEdge(src,res*n+n-1,INF), AddEdge(res*n+n,des,INF);
    		for(int i=1;i<n;++i)
    			AddEdge((res-1)*n+i,res*n+i,INF);
    		for(int i=1;i<=m;++i)
    			AddEdge((res-1)*n+pos[i][(res-1)%num[i]],res*n+pos[i][res%num[i]],v[i]);
    		while(BFS((res+1)*n)) tot+=Dinic(src,INF);
    		if(tot>=k) break;
    	}
    	if(res==500) putchar('0');
    	else printf("%d",res);
    
        return 0;
    }
    
  • 相关阅读:
    学习笔记:松弛
    学习笔记:可持久化线段树
    poj 3784 Running Median
    学习笔记:树状数组
    poj 2823 Sliding Window 题解
    学习笔记:状态压缩DP
    学习笔记:单调队列
    C++ 竞赛常用头文件
    mongodb lock 出毛病时解决方法
    ag使用需要注意的问题
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8417703.html
Copyright © 2011-2022 走看看