zoukankan      html  css  js  c++  java
  • 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("");
    }
    
  • 相关阅读:
    316 Remove Duplicate Letters 去除重复字母
    315 Count of Smaller Numbers After Self 计算右侧小于当前元素的个数
    313 Super Ugly Number 超级丑数
    312 Burst Balloons 戳气球
    309 Best Time to Buy and Sell Stock with Cooldown 买股票的最佳时间含冷冻期
    Java 类成员的初始化顺序
    JavaScript 全局
    HTML字符实体
    Java中的toString()方法
    JavaScript 弹窗
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15811266.html
Copyright © 2011-2022 走看看