• 网络流24题 餐巾计划问题 解题报告


    餐巾计划问题

    这建图太厉害了,我想了巨久都没想到怎么控制流量先合法又能流到别的地方去。

    还是思维太烂了qaq

    用了一个把流量拆开的思路,就叫Ta拆流吧

    具体的说,我们对一个点,有一个流量一定要流,但是这个流量也可以给后面的用,我们就把这个流拆开。

    对应此题,先把点拆成(i)(i+n),然后(i)连接(t)表示流量限制,费用为(0),要流满,这也是整个图唯一连接(t)的边。

    然后(i+n)表示当天用完的这个脏餐巾的流,这个流可以给下一天的脏餐巾,可以送去快洗慢洗再给对应的(j)号点代表(j)得到流

    然后建一下买餐巾的流就可以了


    Code:

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <queue>
    #include <algorithm>
    using std::min;
    #define ll long long
    template <class T>
    void read(T &x)
    {
    	x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    }
    const int N=4010;
    const int M=1e5;
    const int inf=0x3f3f3f3f;;
    int head[N],to[M],Next[M],edge[M],cost[M],cnt=1;
    void add(int u,int v,int w,int c)
    {
    	to[++cnt]=v,edge[cnt]=w,cost[cnt]=c,Next[cnt]=head[u],head[u]=cnt;
    	to[++cnt]=u,edge[cnt]=0,cost[cnt]=-c,Next[cnt]=head[v],head[v]=cnt;
    }
    int n,need[N],s,t;
    int used[N],dis[N],pre[N];
    bool spfa()
    {
    	memset(dis,0x3f,sizeof dis);
    	dis[s]=0;
    	std::queue <int> q;
    	q.push(s);
    	while(!q.empty())
    	{
    		int now=q.front();
    		q.pop();
    		used[now]=0;
    		for(int v,i=head[now];i;i=Next[i])
    			if(edge[i]&&dis[v=to[i]]>dis[now]+cost[i])
    			{
    				dis[v]=dis[now]+cost[i];
    				pre[v]=i;
    				if(!used[v]) q.push(v),used[v]=1;
    			}
    	}
    	return dis[t]<dis[0];
    }
    int main()
    {
    	read(n);
    	for(int i=1;i<=n;i++) read(need[i]);
    	int t1,t2,p0,p1,p2;
    	read(p0),read(t1),read(p1),read(t2),read(p2);
    	s=n<<1|1,t=s+1;
    	for(int i=1;i<=n;i++)
    	{
    		add(s,i,inf,p0);
    		add(i,t,need[i],0);
    		add(s,i+n,need[i],0);
    		if(i<n) add(i+n,i+1+n,inf,0);
    		if(i+t1<=n) add(i+n,i+t1,inf,p1);
    		if(i+t2<=n) add(i+n,i+t2,inf,p2);
    	}
    	ll ans=0;
    	while(spfa())
    	{
    		int mi=inf,now=t;
    		while(pre[now])
    		{
    			mi=min(mi,edge[pre[now]]);
    			now=to[pre[now]^1];
    		}
    		ans+=mi*dis[t];now=t;
    		while(pre[now])
    		{
    			edge[pre[now]]-=mi;
    			edge[pre[now]^1]+=mi;
    			now=to[pre[now]^1];
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    2019.2.26

  • 相关阅读:
    波段是金牢记六大诀窍
    zk kafka mariadb scala flink integration
    Oracle 体系结构详解
    图解 Database Buffer Cache 内部原理(二)
    SQL Server 字符集介绍及修改方法演示
    SQL Server 2012 备份与还原详解
    SQL Server 2012 查询数据库中所有表的名称和行数
    SQL Server 2012 查询数据库中表格主键信息
    SQL Server 2012 查询数据库中所有表的索引信息
    图解 Database Buffer Cache 内部原理(一)
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10438141.html
Copyright © 2020-2023  润新知