• P2050 [NOI2012] 美食节 网络流


    题意:

    戳这里

    分析:

    • 暴力:

      直接上修车的建模, (60pts) 滚粗

    • 正解:

      由于这题菜品数量太多,所以有好多 (id(j,k)) 根本用不上,按照贪心的思想来说,一旦一个厨师开始做菜,他就会连续的做下去,不会中途停下,因为这样不优,所以实际上体现在网络流的模型里面,每个厨师对应的分层图的层一定是连续的,我们就可以一层一层的跑

      最开始我们只把每个菜连向每一个厨师的第一次的位置,每一层找到一个增广的路径,代表这个厨师做了第 (k) 到菜,那么我们把每个菜连向这个厨师的第 (k+1) 次的位置,表示他该做第 (k+1) 次了,这样总的点数都是 (O(m+p)) 边数是 (O(n(m+p))) 的,网络流的玄学复杂度下就过了

    代码:

    #include<bits/stdc++.h>
    #define pii pair<int,int>
    #define mk(x,y) make_pair(x,y)
    #define lc rt<<1
    #define rc rt<<1|1
    #define pb push_back
    #define fir first
    #define sec second
    #define inl inline
    #define reg register
    
    using namespace std;
    
    namespace zzc
    {
    	typedef long long ll;
    	inline int read()
    	{
    		int x=0,f=1;char ch=getchar();
    		while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    		while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    		return x*f;
    	}
    	
    	const int maxn = 1e5+5;
    	const int maxm = 1e7+5;
    	const int inf = 0x3f3f3f3f;
    	int cnt=1,n,m,st,ed,ans,sum;
    	int head[maxn],dis[maxn],flow[maxn],pre[maxn],lst[maxn],p[maxn],t[41][101],dish[maxn],cook[maxn];
    	bool vis[maxn];
    	queue<int> q;
    	struct edge
    	{
    		int to,nxt,w,cst;
    	}e[maxm];
    	
    	inl int id(int x,int y)
    	{
    		return (x-1)*sum+y;
    	}
    	
    	void add(int u,int v,int w,int x)
    	{
    		e[++cnt].to=v;
    		e[cnt].w=w;
    		e[cnt].cst=x;
    		e[cnt].nxt=head[u];
    		head[u]=cnt;
    	}
    	
    	void add_edge(int u,int v,int w,int x)
    	{
    		add(u,v,w,x);add(v,u,0,-x);
    	}
    	
    	bool spfa()
    	{
    		for(int i=st;i<=ed;i++) pre[i]=-1,flow[i]=inf,dis[i]=inf;
    		dis[st]=0;q.push(st);
    		while(!q.empty())
    		{
    			int u=q.front();q.pop();vis[u]=false;
    			for(int i=head[u];i;i=e[i].nxt)
    			{
    				int v=e[i].to;
    				if(e[i].w&&dis[v]>dis[u]+e[i].cst)
    				{
    					dis[v]=dis[u]+e[i].cst;
    					pre[v]=u;
    					lst[v]=i;
    					flow[v]=min(flow[u],e[i].w);
    					if(!vis[v])
    					{
    						vis[v]=true;
    						q.push(v);
    					}
    				}
    			}
    		}
    		return pre[ed]!=-1;
    	}
    	
    	void MCMF()
    	{
    		while(spfa())
    		{
    			int pos=e[lst[ed]^1].to;
    			add_edge(pos+1,ed,1,0);
    			for(int i=1;i<=n;i++) add_edge(m*sum+i,pos+1,1,t[i][cook[pos]]*(dish[pos]+1));
    			
    			int now=ed;
    			ans+=dis[ed]*flow[ed];
    			while(now!=st)
    			{
    				e[lst[now]].w-=flow[ed];
    				e[lst[now]^1].w+=flow[ed];
    				now=pre[now];
    			}
    		}
    	}
    	
    	void work()
    	{
    		n=read();m=read();
    		for(int i=1;i<=n;i++) p[i]=read(),sum+=p[i];
    		st=0;ed=m*sum+n+1;
    		for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) t[i][j]=read(),add_edge(m*sum+i,id(j,1),1,t[i][j]);
    		for(int j=1;j<=m;j++) for(int k=1;k<=sum;k++) cook[id(j,k)]=j,dish[id(j,k)]=k;
    		for(int i=1;i<=n;i++) add_edge(st,m*sum+i,p[i],0);
    		for(int j=1;j<=m;j++) add_edge(id(j,1),ed,1,0);
    		MCMF();
    		printf("%d
    ",ans);
    	}
    
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
  • 相关阅读:
    变量
    注释 & 缩进
    【oracle】生成AWR报告
    【Linux】awk指令
    rhel7.0替换centos yum源
    如何在乌班图上配置java开发环境
    如何在乌版图系统添加拼音输入法!
    如何让虚拟机中乌版图系统变大?
    如何重置虚拟机的乌版图系统的密码?
    虚拟机三种网络模式配置
  • 原文地址:https://www.cnblogs.com/youth518/p/14296655.html
Copyright © 2020-2023  润新知