• CF1288F RedBlue Graph


    一、题目

    点此看题

    二、解法

    其实网络流中严格多于这种限制我们见过很多次了,老方法是计算出具体的边的范围,但是这道题因为边可以为无色,所以我们需要另寻他路。

    原问题的限制其实就是 红-蓝>=1 或者是 蓝-红>=1,这提示我们可以用流量的流入和流出来代表加减,对于原来的一条边 \((u,v)\) 我们把它拆成两个边,向右流代表红,向左流代表蓝。那么对于左部的红点需要 流出-流入>=1,因为要保证流量平衡所以我们从原点补一条下界为 \(1\) 的边即可。

    具体的建图方法可以看下图,三元组 \((l,r,c)\) 分别表示流量的下界、上界、权值:

    那么跑有源汇上下界最小费用可行流即可。

    三、总结

    加减的不等式关系可以用循环流量抵消\(+\)上下界网络流来完成。

    #include <cstdio>
    #include <iostream>
    #include <queue>
    using namespace std;
    const int M = 1005;
    const int inf = 0x3f3f3f3f;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n1,n2,m,R,B,s1,t1,S,T,d[M];char sa[M],sb[M];
    int tot=1,f[M],dis[M],flow[M],pre[M],lst[M];
    struct edge
    {
    	int v,f,c,next;
    }e[M*M];
    void add(int u,int v,int l,int r,int c)
    {
    	d[u]-=l;d[v]+=l;
    	e[++tot]=edge{v,r-l,c,f[u]},f[u]=tot;
    	e[++tot]=edge{u,0,-c,f[v]},f[v]=tot;
    }
    int bfs()
    {
    	queue<int> q;
    	for(int i=0;i<=T;i++)
    		dis[i]=inf,flow[i]=pre[i]=lst[i]=0;
    	dis[S]=0;flow[S]=inf;q.push(S);
    	while(!q.empty())
    	{
    		int u=q.front();q.pop();
    		for(int i=f[u];i;i=e[i].next)
    		{
    			int v=e[i].v,c=e[i].c;
    			if(dis[v]>dis[u]+c && e[i].f>0)
    			{
    				dis[v]=dis[u]+c;
    				flow[v]=min(flow[u],e[i].f);
    				pre[v]=u;lst[v]=i;
    				q.push(v);
    			}
    		}
    	}
    	return flow[T]>0;
    }
    signed main()
    {
    	n1=read();n2=read();m=read();R=read();B=read();
    	scanf("%s%s",sa+1,sb+1);
    	s1=n1+n2+1;t1=s1+1;S=t1+1;T=S+1;
    	for(int i=1;i<=m;i++)
    	{
    		int u=read(),v=read();
    		add(u,v+n1,0,1,R);
    		add(v+n1,u,0,1,B);
    	}
    	for(int i=1;i<=n1;i++)
    	{
    		if(sa[i]=='R') add(s1,i,1,inf,0);
    		else if(sa[i]=='B') add(i,t1,1,inf,0);
    		else add(s1,i,0,inf,0),add(i,t1,0,inf,0);
    	}
    	for(int i=1;i<=n2;i++)
    	{
    		if(sb[i]=='R') add(i+n1,t1,1,inf,0);
    		else if(sb[i]=='B') add(s1,i+n1,1,inf,0);
    		else add(s1,i+n1,0,inf,0),add(i+n1,t1,0,inf,0);
    	}
    	add(t1,s1,0,inf,0);
    	int ans=0,cost=0,sum=0;
    	for(int i=1;i<=t1;i++)
    	{
    		if(d[i]>0) sum+=d[i],add(S,i,0,d[i],0);
    		if(d[i]<0) add(i,T,0,-d[i],0);
    	}
    	while(bfs())
    	{
    		ans+=flow[T];int nw=T;
    		cost+=flow[T]*dis[T];
    		while(nw!=S)
    		{
    			e[lst[nw]].f-=flow[T];
    			e[lst[nw]^1].f+=flow[T];
    			nw=pre[nw];
    		}
    	}
    	if(ans<sum) {puts("-1");return 0;}
    	printf("%d\n",cost);
    	for(int i=2;i<=4*m;i+=4)
    	{
    		if(!e[i].f) putchar('R');
    		else if(!e[i+2].f) putchar('B');
    		else putchar('U');
    	}
    	puts("");
    }
    
  • 相关阅读:
    office 365 sharepoint online 学习资料
    NPOI 导入 导出 Excel
    800703fa Illegal operation attempted on a registry key that has been marked for deletion
    js 获取身份证号码出生日期,籍贯等信息
    直接在浏览器中修改网页内容
    asp.net 按指定模板导出word,pdf
    StackPanel在增加控件的问题
    解决iOS工程被Xcode识别成Mac工程的问题
    Swift之异常处理
    Swift中的协议和闭包
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15811266.html
Copyright © 2020-2023  润新知