首页 > 其他分享 >P4003 [清华集训 2017] 无限之环 解题报告

P4003 [清华集训 2017] 无限之环 解题报告

时间:2024-06-05 10:33:49浏览次数:12  
标签:int flow 之环 id add edge edgenum 2017 P4003

oj:https://gxyzoj.com/d/gxyznoi/p/P93

它要判断什么时候不漏水,就是需要建一种图,使得原图的最大流是答案

因为是网格图,考虑黑白染色,可以将\((i+j)\)对2取模的结果作为颜色,将所有颜色为1的点向源点连边,颜色为0的点向汇点连边

接下来考虑如何判断是否漏水,因为有四个方向,考虑拆点

将每个点拆为上下左右四个周围点和一个中间点,然后此时就可以将能流到的方向与其对应的点相连

接下来考虑旋转,虽然原图共有15种情况,实则可以分成5大类

  1. 一条出边

上图中的边朝上,所以向右或向左均需转一次,而向下需转两次,所以可以从上向左和有分别连一条边权为1的边,向下连一条边权为2的边

  1. 直线型

因为无法旋转,直接连边即可

  1. L型

显然,转一次可以使朝上的边向下或使朝右的边向左,所以可以从上向下,从右向左分别连一条边权为1的边

接着考虑旋转2次的情况,其实就是将两条边跑满,所以不用另外建边

  1. 三条出边

和一条出边类似,将左或右转到下方需要1次,上方的转到下方需要2次

  1. 十字型

显然不需要旋转

此时,求费用即可

代码:

#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=1e9;
int n,m,head[20005],edgenum=1,s,t;
struct edge{
	int to,nxt,val,flow;
}e[5000006];
void add_edge(int u,int v,int f,int w)
{
	e[++edgenum].nxt=head[u];
	e[edgenum].to=v;
	e[edgenum].val=w;
	e[edgenum].flow=f;
	head[u]=edgenum;
}
void link(int u,int v,int f,int w)
{
	add_edge(u,v,f,w);
	add_edge(v,u,0,-w);
}
int id(int x,int y,int tmp)
{
	return (x-1)*m*5+(y-1)*5+tmp;
}
// mid=5,right=2/1,up=1/10,left=4/100,down=3/1000
int dx[5]={-1,0,0,1},dy[5]={0,-1,1,0};
int c1[5]={1,4,2,3},c2[5]={3,2,4,1};
int sum;
void link1(int x,int y,int z,int col)
{
	if(col)
	{
		link(s,id(x,y,5),inf,0);
		for(int i=0;i<4;i++)
		{
			int tx=x+dx[i],ty=y+dy[i];
			if(tx<1||ty<1||tx>n||ty>m) continue;
			link(id(x,y,c1[i]),id(tx,ty,c2[i]),1,0);
		}
		for(int i=0;i<4;i++)
		{
			if((1<<i)&z)
			{
				link(id(x,y,5),id(x,y,i+1),1,0);
				sum++;
			}
		}
		if(z==1)//1
		{
			link(id(x,y,1),id(x,y,2),1,1);
			link(id(x,y,1),id(x,y,3),1,2);
			link(id(x,y,1),id(x,y,4),1,1);
		}
		if(z==2)//10
		{
			link(id(x,y,2),id(x,y,4),1,2);
			link(id(x,y,2),id(x,y,3),1,1);
			link(id(x,y,2),id(x,y,1),1,1);
		}
		if(z==4)//100
		{
			link(id(x,y,3),id(x,y,1),1,2);
			link(id(x,y,3),id(x,y,2),1,1);
			link(id(x,y,3),id(x,y,4),1,1);
		}
		if(z==8)//1000
		{
			link(id(x,y,4),id(x,y,1),1,1);
			link(id(x,y,4),id(x,y,2),1,2);
			link(id(x,y,4),id(x,y,3),1,1);
		}
		if(z==3)//10+1
		{
			link(id(x,y,1),id(x,y,3),1,1);
			link(id(x,y,2),id(x,y,4),1,1);
		}
		if(z==6)//100+10
		{
			link(id(x,y,2),id(x,y,4),1,1);
			link(id(x,y,3),id(x,y,1),1,1);
		}
		if(z==9)//1000+1
		{
			link(id(x,y,1),id(x,y,3),1,1);
			link(id(x,y,4),id(x,y,2),1,1);
		}
		if(z==12)//1000+100
		{
			link(id(x,y,4),id(x,y,2),1,1);
			link(id(x,y,3),id(x,y,1),1,1);
		}
		if(z==7)//100+10+1
		{
			link(id(x,y,1),id(x,y,4),1,1);
			link(id(x,y,2),id(x,y,4),1,2);
			link(id(x,y,3),id(x,y,4),1,1);
		}
		if(z==11)//1000+10+1
		{
			link(id(x,y,1),id(x,y,3),1,2);
			link(id(x,y,2),id(x,y,3),1,1);
			link(id(x,y,4),id(x,y,3),1,1);
		}
		if(z==13)//1000+100+1
		{
			link(id(x,y,1),id(x,y,2),1,1);
			link(id(x,y,3),id(x,y,2),1,1);
			link(id(x,y,4),id(x,y,2),1,2);
		}
		if(z==14)//1000+100+10
		{
			link(id(x,y,2),id(x,y,1),1,1);
			link(id(x,y,3),id(x,y,1),1,2);
			link(id(x,y,4),id(x,y,1),1,1);
		}
	}
	else
	{
		link(id(x,y,5),t,inf,0);
		for(int i=0;i<4;i++)
		{
			if((1<<i)&z)
			{
				link(id(x,y,i+1),id(x,y,5),1,0);
				sum++;
			}
		}
		if(z==1)//1
		{
			link(id(x,y,2),id(x,y,1),1,1);
			link(id(x,y,3),id(x,y,1),1,2);
			link(id(x,y,4),id(x,y,1),1,1);
		}
		if(z==2)//10
		{
			link(id(x,y,4),id(x,y,2),1,2);
			link(id(x,y,3),id(x,y,2),1,1);
			link(id(x,y,1),id(x,y,2),1,1);
		}
		if(z==4)//100
		{
			link(id(x,y,1),id(x,y,3),1,2);
			link(id(x,y,2),id(x,y,3),1,1);
			link(id(x,y,4),id(x,y,3),1,1);
		}
		if(z==8)//1000
		{
			link(id(x,y,1),id(x,y,4),1,1);
			link(id(x,y,2),id(x,y,4),1,2);
			link(id(x,y,3),id(x,y,4),1,1);
		}
		if(z==3)//10+1
		{
			link(id(x,y,4),id(x,y,2),1,1);
			link(id(x,y,3),id(x,y,1),1,1);
		}
		if(z==6)//100+10
		{
			link(id(x,y,1),id(x,y,3),1,1);
			link(id(x,y,4),id(x,y,2),1,1);
		}
		if(z==9)//1000+1
		{
			link(id(x,y,2),id(x,y,4),1,1);
			link(id(x,y,3),id(x,y,1),1,1);
		}
		if(z==12)//1000+100
		{
			link(id(x,y,1),id(x,y,3),1,1);
			link(id(x,y,2),id(x,y,4),1,1);
		}
		if(z==7)//100+10+1
		{
			link(id(x,y,4),id(x,y,1),1,1);
			link(id(x,y,4),id(x,y,2),1,2);
			link(id(x,y,4),id(x,y,3),1,1);
		}
		if(z==11)//1000+10+1
		{
			link(id(x,y,3),id(x,y,1),1,2);
			link(id(x,y,3),id(x,y,2),1,1);
			link(id(x,y,3),id(x,y,4),1,1);
		}
		if(z==13)//1000+100+1
		{
			link(id(x,y,2),id(x,y,1),1,1);
			link(id(x,y,2),id(x,y,3),1,1);
			link(id(x,y,2),id(x,y,4),1,2);
		}
		if(z==14)//1000+100+10
		{
			link(id(x,y,1),id(x,y,2),1,1);
			link(id(x,y,1),id(x,y,3),1,2);
			link(id(x,y,1),id(x,y,4),1,1);
		}
	}
}
int flow[20005],dis[20005],pre[20005],pos[20005];
bool inq[20005];
queue<int> q;
bool spfa(int x,int y)
{
	for(int i=0;i<=t;i++)
	{
		dis[i]=flow[i]=inf,inq[i]=0;
	}
	q.push(x);
	dis[x]=0;
	inq[x]=1;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		inq[u]=0;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to,w=e[i].val,f=e[i].flow;
			if(f&&dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				flow[v]=min(flow[u],f);
				pre[v]=u,pos[v]=i;
				if(!inq[v])
				{
					inq[v]=1;
					q.push(v);
				}
			}
		}
	}
	if(dis[y]<inf) return 1;
	return 0;
}
int cost,cnt;
void MCMF()
{
	cost=cnt=0;
	while(spfa(s,t))
	{
		cnt+=flow[t];
		cost+=flow[t]*dis[t];
		int x=t;
		while(x!=s)
		{
			int p=pos[x];
			e[p].flow-=flow[t];
			e[p^1].flow+=flow[t];
			x=pre[x];
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	t=n*m*5+5;
	for(int i=1;i<=n;i++)
	{
		int col=i%2;
		for(int j=1;j<=m;j++)
		{
			int x;
			scanf("%d",&x);
			link1(i,j,x,col);
			col^=1;
		}
	}
	MCMF();
	if(cnt*2==sum)
	printf("%d",cost);
	else printf("-1");
	return 0;
}

标签:int,flow,之环,id,add,edge,edgenum,2017,P4003
From: https://www.cnblogs.com/wangsiqi2010916/p/18232462

相关文章

  • P6342 [CCO2017] Vera 与道路建设 题解
    题目大意对于一个图w一共有v个点点的编号为1,2,...,v,对于点a与点b如果满足$a\tob$且$b\toa$使得每一条道路都只走过一次,那么我们称$a,b$为完美点对,当一个联通图只有$k$个完美点对时,称这个联通图为美丽公路网,要求求出一个美丽公路网......
  • 【NOIP2017普及组复赛】题2:图书管理员
    题2:图书管理员【题目描述】图书馆中每本书都有一个图书编码,可以用于快速检索图书,这个图书编码是一个正整数。每位借书的读者手中有一个需求码,这个需求码也是一个正整数。如果一本书的图书编码恰好以读者的需求码结尾,那么这本书就是这位读者所需要的。小......
  • P8655 [蓝桥杯 2017 国 B] 发现环
    原题链接题解有点像拓扑排序拓扑排序怎么做来着?首先找老祖节点对不对?老祖节点有什么特性?入度为零而在无向图中,我们把叶子节点看成老祖节点,它们有什么特性?连接的边只有一条code#include<bits/stdc++.h>usingnamespacestd;vector<int>G[100005];intcon[100005]={......
  • [Usaco2017 Open]Bovine Genomics 题解^&*^(
    不知道为啥,我死活想不到二分(楼下正解)所以,就有了这篇题解可以看到,这道题离暴力的距离只有一步!就是数组开不下!!小问答:数组开不下时,你会?A:mapB:优化代码C:gp_hash_table由于正在学hash,所以容易想到...tong[本来的下标%9999999]然后就玄学的过了。。。ACcode#include<bi......
  • CVE-2017-2824
    ZabbixServertrapper命令注入漏洞(CVE-2017-2824)Zabbix是由AlexeiVladishev开发的一种网络监视、管理系统,基于Server-Client架构。其Server端trappercommand功能存在一处代码执行漏洞,特定的数据包可造成命令注入,进而远程执行代码。攻击者可以从一个Zabbixproxy发起请求......
  • C121 李超树+DP P4655 [CEOI2017] Building Bridges
    视频链接:C121李超树+DPP4655[CEOI2017]BuildingBridges_哔哩哔哩_bilibili   LuoguP4655[CEOI2017]BuildingBridges#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;#definelllonglong#definelsu<<......
  • VS2017+QT5.9.1 自定义loggerControl
    创建自定义类LoggerControl继承QListWidget#pragmaonce#include<QListWidget>#include"Helper.h"#include<QTime>#include<QPainter>classLoggerControl:publicQListWidget{Q_OBJECTpublic:LoggerControl(QWidget*paren......
  • [ICPC2017 WF] Scenery
    提供一个\(O(n^2\alpha(n))\)的做法。这种匹配问题如果直接寻找最优的匹配方式是困难的,因为\(\geqslantk\)的限制,当前匹配的点会对之后的产生不小的影响。但是如果我们\(\text{fix}\)好了一个选择的升序位置序列\(a\),想要判定其是否合法是容易的,需要以下两个条件:\(1.\)......
  • Spring WebFlow 远程代码执行漏洞(CVE-2017-4971)
    SpringWebFlow远程代码执行漏洞(CVE-2017-4971)SpringWebFlow是一个适用于开发基于流程的应用程序的框架(如购物逻辑),可以将流程的定义和实现流程行为的类和视图分离开来。在其2.4.x版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,最终造成任意命令执行。......
  • Qt Creator + MSVC2017编译器配置指南
    QtCreator+MSVC2017编译器配置指南下载和安装MSVC2017编译器下载下载MSVC编译器安装工具:https://docs.microsoft.com/zh-tw/previous-versions/visualstudio/visual-studio-2017/install/use-command-line-parameters-to-install-visual-studio?view=vs-2017安装安......