POJ 2396 有源有汇有上下界可行流问题
题意:给一个矩阵,给出每行每列之和,附加一些条件,如第i行第j列数必需大于(小于)多少。
思路题解:矩阵模型,模拟网络流,行、列标号为结点,构图,附加s,t,s连行标(容量上下限每行之和(必需以这个
值全部送过去),每个列标连向t(容量上下限每列之和)),其他每个行到列都有边(有限制的按限制
来,无限制的自己添加)。由于s->网络->t,若有解,总流量f必为
矩阵所有数之和,故添加边t-S,容量上下线为矩阵和sum,这样保证了每个点出入流相等,满足流量平衡,
转化为无源无汇有上下线可行流问题,在建立超级源点汇点ss,tt,按无源无汇法做一遍ss->tt最大流,
判断可行即可。可行输出方案。PS,若题目改为求有源有汇有限制最大流问题,可以在残量网络再走一次
s->t(原图源汇)最大流(solo可行的后悔边啥~)
此题,有源有汇有限制可行流问题,主要是建图,就是一个字烦!其一:0的时候要所有,行列为0要
讨论,其二,>,<,=符号的判定,讨论下,其三,重边,这个不是链前星锁解决那个重边,而是重边
是“且”的关系,如,先给上限,再来一边给下限!坑爹啊这是要!无法,hash判重吧,重了,再修改原来的
边,要搞清楚反向边(建图时跑第一次(第一次判断有无解)前)流量始终为0(提供后悔的,和之后没有
半毛钱关系)!至于算法,不再是问题,dinic跑的。
#include<iostream> //47ms,1A
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
int n,m;const int inf=0x3f3f3f3f;
int suminf[300];int sumouf[300];
int e[20000][5]; int head[300];int level[300];int vis[300];
int hash[250][300];int ans[250][300];
int nume=0;
bool bfs() //dinic“d,bfs”,不用说了
{
for(int i=0;i<n+m+4;i++)
level[i]=vis[i]=0;
vis[n+m+2]=1;
queue<int>q;q.push(n+m+2);
while(!q.empty())
{
int cur=q.front();q.pop();
for(int i=head[cur];i!=-1;i=e[i][1])
{
int v=e[i][0];
if(!vis[v]&&e[i][2]>0)
{
level[v]=level[cur]+1;
vis[v]=1;
if(v==m+n+3)return 1;
q.push(v);
}
}
}
return vis[n+m+3];
}
int dfs(int u,int minf)
{
if(u==n+m+3||minf==0){return minf;}
int sumf=0,f;
for(int i=head[u];i!=-1&&minf;i=e[i][1])
{
int v=e[i][0];
if(level[v]==level[u]+1&&e[i][2]>0)
{
f=dfs(v,minf<e[i][2]?minf:e[i][2]);
if(f==0)continue;
e[i][2]-=f;e[i^1][2]+=f;
minf-=f;sumf+=f;
}
}
return sumf;
}
void dinic()
{
int sumflow=0;
while(bfs())
{
sumflow+=dfs(n+m+2,inf);
}
}
bool check() //无源无汇的,出发点ss(超级源点)的边有一条不满流就无解,原因简单必需保证流量平衡(为之提供下限)
{
for(int i=head[n+m+2];i!=-1;i=e[i][1])
{
if(e[i][2]!=0)return 0;
}
return 1;
}
int main()
{
int N;
scanf("%d",&N);
while(N--) //N组输入
{
scanf("\n%d%d",&n,&m); //忽略空行
nume=0;
int sum=0,temp;
bool mark=0;
for(int i=0;i<=n+m+5;i++)
{
head[i]=-1;
suminf[i]=sumouf[i]=0;
}
for(int i=0;i<=n;i++)
for(int j=n+1;j<=n+m+1;j++)
ans[i][j]=hash[i][j]=0;
for(int i=1;i<=n;i++) //有源有汇的源点s
{
scanf("%d",&temp);sum+=temp;
e[nume][0]=i;e[nume][1]=head[0];head[0]=nume;
e[nume][2]=0;e[nume][3]=temp;e[nume++][4]=temp;
suminf[i]+=temp;sumouf[0]+=temp;
e[nume][0]=0;e[nume][1]=head[i];head[i]=nume;
e[nume++][2]=0;
}
for(int i=n+1;i<=m+n;i++) //汇点t
{
scanf("%d",&temp);
e[nume][0]=n+1+m;e[nume][1]=head[i];head[i]=nume;
e[nume][2]=0;e[nume][3]=temp;e[nume++][4]=temp;
suminf[n+m+1]+=temp;sumouf[i]+=temp;
e[nume][0]=i;e[nume][1]=head[n+m+1];head[n+m+1]=nume;
e[nume++][2]=0;
}
e[nume][0]=0;e[nume][1]=head[n+m+1];head[n+m+1]=nume; //添加t->s
e[nume][2]=0;e[nume][3]=sum;e[nume++][4]=sum;
suminf[0]+=sum;sumouf[n+m+1]+=sum;
e[nume][0]=n+m+1;e[nume][1]=head[0];head[0]=nume;
e[nume++][2]=0;
int ca;scanf("%d",&ca); int row,col,lim;char cc;
for(int i=0;i<ca;i++) //按条件建图
{
scanf("%d%d %c %d",&row,&col,&cc,&lim);
if(col!=0&&row==0)
{
if(cc=='=')
for(int i=1;i<=n;i++)
{
if(hash[i][n+col]) //判重,下面一致
{
int pp;
for( pp=head[i];e[pp][0]!=n+col;pp=e[pp][1])
;
suminf[n+col]-=e[pp][3]; sumouf[i]-=e[pp][3];
if(lim>e[pp][3])e[pp][3]=lim;
if(lim<e[pp][4])e[pp][4]=lim;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[n+col]+=e[pp][3]; sumouf[i]+=e[pp][3];
}
else
{
e[nume][0]=n+col;e[nume][1]=head[i];head[i]=nume;
e[nume][2]=0;e[nume][3]=lim;e[nume++][4]=lim; suminf[n+col]+=lim; sumouf[i]+=lim;hash[i][n+col]=1;
e[nume][0]=i;e[nume][1]=head[n+col];head[n+col]=nume;
e[nume++][2]=0;
}
}
else if(cc=='>')
{
for(int i=1;i<=n;i++)
{
if(hash[i][n+col])
{ int pp;
for( pp=head[i];e[pp][0]!=n+col;pp=e[pp][1])
;
suminf[n+col]-=e[pp][3]; sumouf[i]-=e[pp][3];
if(lim+1>e[pp][3])e[pp][3]=lim+1;
if(inf<e[pp][4])e[pp][4]=inf;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[n+col]+=e[pp][3]; sumouf[i]+=e[pp][3];
}
else
{ e[nume][0]=n+col;e[nume][1]=head[i];head[i]=nume;
e[nume][2]=inf-lim-1;e[nume][3]=lim+1;e[nume++][4]=inf;
suminf[n+col]+=lim+1; sumouf[i]+=lim+1;hash[i][n+col]=1;
e[nume][0]=i;e[nume][1]=head[n+col];head[n+col]=nume;
e[nume++][2]=0;
}
}
}
else if(cc=='<')
{
for(int i=1;i<=n;i++)
if(hash[i][n+col])
{ int pp;
for(pp=head[i];e[pp][0]!=n+col;pp=e[pp][1])
;
suminf[n+col]-=e[pp][3]; sumouf[i]-=e[pp][3];
if(0>e[pp][3])e[pp][3]=0;
if(lim-1<e[pp][4])e[pp][4]=lim-1;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[n+col]+=e[pp][3]; sumouf[i]+=e[pp][3];
}
else
{
e[nume][0]=n+col;e[nume][1]=head[i];head[i]=nume;
e[nume][2]=lim-1;e[nume][3]=0;e[nume++][4]=lim-1;hash[i][n+col]=1;
//inf[n+rol]+=lim; sumouf[i]+=lim;
e[nume][0]=i;e[nume][1]=head[n+col];head[n+col]=nume;
e[nume++][2]=0;
}
} }
else if(row!=0&&col==0)
{
if(cc=='>')
{
for(int i=n+1;i<=n+m;i++)
{ if(hash[row][i])
{ int pp;
for( pp=head[row];e[pp][0]!=i;pp=e[pp][1])
;
suminf[i]-=e[pp][3]; sumouf[row]-=e[pp][3];
if(lim+1>e[pp][3])e[pp][3]=lim+1;
if(inf<e[pp][4])e[pp][4]=inf;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[i]+=e[pp][3]; sumouf[row]+=e[pp][3];
}
else
{
e[nume][0]=i;e[nume][1]=head[row];head[row]=nume;
e[nume][2]=inf-lim-1;e[nume][3]=lim+1;e[nume++][4]=inf;
suminf[i]+=lim+1; sumouf[row]+=lim+1;hash[row][i]=1;
e[nume][0]=row;e[nume][1]=head[i];head[i]=nume;
e[nume++][2]=0;
}
}
}
else if(cc=='=')
for(int i=n+1;i<=n+m;i++)
{
if(hash[row][i])
{ int pp;
for(pp=head[row];e[pp][0]!=i;pp=e[pp][1])
;
suminf[i]-=e[pp][3]; sumouf[row]-=e[pp][3];
if(lim>e[pp][3])e[pp][3]=lim;
if(lim<e[pp][4])e[pp][4]=lim;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[i]+=e[pp][3]; sumouf[row]+=e[pp][3];
}
else
{ e[nume][0]=i;e[nume][1]=head[row];head[row]=nume;
e[nume][2]=0;e[nume][3]=lim;e[nume++][4]=lim;
suminf[i]+=lim; sumouf[row]+=lim;hash[row][i]=1;
e[nume][0]=row;e[nume][1]=head[i];head[i]=nume;
e[nume++][2]=0;
}
}
else if(cc=='<')
for(int i=n+1;i<=n+m;i++)
{
if(hash[row][i])
{ int pp;
for( pp=head[row];e[pp][0]!=i;pp=e[pp][1])
;
suminf[i]-=e[pp][3]; sumouf[row]-=e[pp][3];
if(0>e[pp][3])e[pp][3]=0;
if(lim-1<e[pp][4])e[pp][4]=lim-1;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[i]+=e[pp][3]; sumouf[row]+=e[pp][3];
}
else
{
e[nume][0]=i;e[nume][1]=head[row];head[row]=nume;
e[nume][2]=lim-1;e[nume][3]=0;e[nume++][4]=lim-1;hash[row][i]=1;
//inf[i]+=lim; sumouf[row]+=lim;
e[nume][0]=row;e[nume][1]=head[i];head[i]=nume;
e[nume++][2]=0;
}
}
}
else if(row==0&&col==0)
{
if(cc=='=')
{
for(int i=1;i<=n;i++)
for(int j=n+1;j<=n+m;j++)
{
if(hash[i][j])
{ int pp;
for( pp=head[i];e[pp][0]!=j;pp=e[pp][1])
;
suminf[j]-=e[pp][3]; sumouf[i]-=e[pp][3];
if(lim>e[pp][3])e[pp][3]=lim;
if(lim<e[pp][4])e[pp][4]=lim;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[j]+=e[pp][3]; sumouf[i]+=e[pp][3];
}
else
{
e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
e[nume][2]=0;e[nume][3]=lim;e[nume++][4]=lim;
suminf[j]+=lim; sumouf[i]+=lim;hash[i][j]=1;
e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;
e[nume++][2]=0;
}
}
}
if(cc=='>')
{
for(int i=1;i<=n;i++)
for(int j=n+1;j<=n+m;j++)
{
if(hash[i][j])
{ int pp;
for( pp=head[i];e[pp][0]!=j;pp=e[pp][1])
;
suminf[j]-=e[pp][3]; sumouf[i]-=e[pp][3];
if(lim+1>e[pp][3])e[pp][3]=lim+1;
if(inf<e[pp][4])e[pp][4]=inf;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[j]+=e[pp][3]; sumouf[i]+=e[pp][3];
}
else
{
e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
e[nume][2]=inf-lim-1;e[nume][3]=lim+1;e[nume++][4]=inf;
suminf[j]+=lim+1; sumouf[i]+=lim+1;hash[i][j]=1;
e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;
e[nume++][2]=0;
}
}
}
if(cc=='<')
for(int i=1;i<=n;i++)
for(int j=n+1;j<=n+m;j++)
{
if(hash[i][j])
{ int pp;
for( pp=head[i];e[pp][0]!=j;pp=e[pp][1])
;
suminf[j]-=e[pp][3]; sumouf[i]-=e[pp][3];
if(0>e[pp][3])e[pp][3]=0;
if(lim-1<e[pp][4])e[pp][4]=lim-1;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[j]+=e[pp][3]; sumouf[i]+=e[pp][3];
}
else
{
e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
e[nume][2]=lim-1;e[nume][3]=0;e[nume++][4]=lim-1;hash[i][j]=1;
//inf[j]+=lim; sumouf[i]+=lim;
e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;
e[nume++][2]=0;
}
}
}
else
{
if(cc=='=')
{
if(hash[row][n+col])
{ int pp;
for(pp=head[row];e[pp][0]!=n+col;pp=e[pp][1])
;
suminf[n+col]-=e[pp][3]; sumouf[row]-=e[pp][3];
if(lim>e[pp][3])e[pp][3]=lim;
if(lim<e[pp][4])e[pp][4]=lim;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[n+col]+=e[pp][3]; sumouf[row]+=e[pp][3];
}
else
{
e[nume][0]=col+n;e[nume][1]=head[row];head[row]=nume;
e[nume][2]=0;e[nume][3]=lim;e[nume++][4]=lim;
suminf[col+n]+=lim; sumouf[row]+=lim;hash[row][col+n]=1;
e[nume][0]=row;e[nume][1]=head[col+n];head[col+n]=nume;
e[nume++][2]=0;
}
}
else if(cc=='>')
{
if(hash[row][n+col])
{ int pp;
for(pp=head[row];e[pp][0]!=n+col;pp=e[pp][1])
;
suminf[n+col]-=e[pp][3]; sumouf[row]-=e[pp][3];
if(lim+1>e[pp][3])e[pp][3]=lim+1;
if(inf<e[pp][4])e[pp][4]=inf;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[n+col]+=e[pp][3]; sumouf[row]+=e[pp][3];
}
else
{
e[nume][0]=col+n;e[nume][1]=head[row];head[row]=nume;
e[nume][2]=inf-lim-1;e[nume][3]=lim+1;e[nume++][4]=inf;
suminf[col+n]+=lim+1; sumouf[row]+=lim+1;hash[row][col+n]=1;
e[nume][0]=row;e[nume][1]=head[col+n];head[col+n]=nume;
e[nume++][2]=0;
}
}
else if(cc=='<')
{
if(hash[row][n+col])
{ int pp;
for( pp=head[row];e[pp][0]!=n+col;pp=e[pp][1])
;
suminf[n+col]-=e[pp][3]; sumouf[row]-=e[pp][3];
if(0>e[pp][3])e[pp][3]=0;
if(lim-1<e[pp][4])e[pp][4]=lim-1;
if(e[pp][3]>e[pp][4])mark=1;
e[pp][2]=e[pp][4]-e[pp][3];
suminf[n+col]+=e[pp][3]; sumouf[row]+=e[pp][3];
}
else
{ e[nume][0]=col+n;e[nume][1]=head[row];head[row]=nume;
e[nume][2]=lim-1;e[nume][3]=0;e[nume++][4]=lim-1;hash[row][col+n]=1;
// inf[col]+=lim; sumouf[row]+=lim;
e[nume][0]=row;e[nume][1]=head[col+n];head[col+n]=nume;
e[nume++][2]=0;
}
}
}
}
for(int i=1;i<=n;i++) //有些边没有限制,不要忘记加边!!
for(int j=n+1;j<=n+m;j++)
if(!hash[i][j])
{
e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
e[nume][4]=inf;e[nume++][2]=inf;
e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;
e[nume++][2]=0;
}
//无源无汇添加ss,tt
for(int i=0;i<=n+m+1;i++)
{
e[nume][0]=i;e[nume][1]=head[n+m+2];head[n+m+2]=nume;
e[nume++][2]=suminf[i];
e[nume][0]=n+m+2;e[nume][1]=head[i];head[i]=nume;
e[nume++][2]=0; e[nume][0]=n+m+3;e[nume][1]=head[i];head[i]=nume;
e[nume++][2]=sumouf[i];
e[nume][0]=i;e[nume][1]=head[n+m+3];head[n+m+3]=nume;
e[nume++][2]=0;
}
dinic(); //从ss->tt,判断有无解
if(mark||!check())printf("IMPOSSIBLE\n");
else //输出答案
{
for(int i=1;i<=n;i++)
for(int j=head[i];j!=-1;j=e[j][1])
ans[i][e[j][0]]=e[j][4]-e[j][2]; //原来上限-残留量,即为所用(上限-下限-残留+下限)
for(int i=1;i<=n;i++)
for(int j=n+1;j<=n+m;j++)
{
if(j!=n+m)printf("%d ",ans[i][j]);
else printf("%d\n",ans[i][j]);
}
}
if(N!=0)printf("\n");
}
return 0;
}
POJ 2396 有源有汇有上下界可行流问题的更多相关文章
- [poj] 2396 [zoj] 1994 budget || 有源汇的上下界可行流
poj原题 zoj原题 //注意zoj最后一行不要多输出空行 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表不同赛区支出的矩阵.组委会曾经开会讨论过各类支出的总和,以及各赛区 ...
- SGU 176 Flow construction (有源有汇有上下界最小流)
题意:给定 n 个点,m 条有向边,如果有向边的标号是1的话,就表示该边的上界下界都为容量 ,如果有向边的标号为0的哈,表示该边的下界为0,上界为容量 ,现在问,从 1 到 n 的最小流是多少,并输出 ...
- 无源汇有上下界可行流(ZQU 1590)
无源汇有上下界可行流(也就是循环流) 模型:一个网络,求出一个流,使得每条边的流量必须>=Li且<=Hi, 每个点必须满足总流入量=总流出量(流量守恒)(这个流的特点是循环往复,无始无终) ...
- LOJ [#115. 无源汇有上下界可行流](https://loj.ac/problem/115)
#115. 无源汇有上下界可行流 先扔个板子,上下界的东西一点点搞,写在奇怪的合集里面 Code: #include <cstdio> #include <cstring> # ...
- 2018.08.20 loj#115. 无源汇有上下界可行流(模板)
传送门 又get到一个新技能,好兴奋的说啊. 一道无源汇有上下界可行流的模板题. 其实这东西也不难,就是将下界变形而已. 准确来说,就是对于每个点,我们算出会从它那里强制流入与流出的流量,然后与超级源 ...
- [loj#115] 无源汇有上下界可行流 网络流
#115. 无源汇有上下界可行流 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题 ...
- loj#115. 无源汇有上下界可行流
\(\color{#0066ff}{ 题目描述 }\) 这是一道模板题. \(n\) 个点,\(m\) 条边,每条边 \(e\) 有一个流量下界 \(\text{lower}(e)\) 和流量上界 \ ...
- 【LOJ115】无源汇有上下界可行流(模板题)
点此看题面 大致题意: 给你每条边的流量上下界,让你判断是否存在可行流.若有,则还需输出一个合法方案. 大致思路 首先,每条边既然有一个流量下界\(lower\),我们就强制它初始流量为\(lower ...
- Zoj 2314 Reactor Cooling(无源汇有上下界可行流)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 题意: 给n个点,及m根pipe,每根pipe用来流躺液体的,单向 ...
随机推荐
- 接口和类方法中的 SELF
接口和类方法中的 SELF 由 王巍 (@ONEVCAT) 发布于 2015/06/10 我们在看一些接口的定义时,可能会注意到出现了首字母大写的 Self 出现在类型的位置上: protocol I ...
- CentOS7支持中文显示
1.查看系统是否安装有中文语言包 locale -a | grep "zh_CN" 命令含义:列出所有可用的公共语言环境的名称,包含有"zh_CN" 若 ...
- database---many to many relationships(多对多关系型数据库)
Many to many Relationships A many-to-many relationship occurs when multiple records in a table are a ...
- nginx常用功能配置
一.规范优化nginx配置文件 nginx的主配置文件为nginx.conf,主配置文件包含的所有虚拟主机的子配置文件会统一放入extra目录中,虚拟主机的配置文件按照网站的域名或功能取名,例如www ...
- day14 迭代器,生成器,函数的递归调用
1.什么是迭代器 迭代是一个重复的过程,但是每次重复都是基于上一次重复的结果而继续 迭代取值的工具 2.为什么要用迭代器 迭代器的优点 ①不依赖于索引取值 ②更节省内存 缺点: 1.不如按 ...
- wordpress配置SMTP服务发送邮件(qq邮箱)
wordpress有一个注册功能,填了用户名和邮箱后,会收到一封邮件,邮件里有一个链接,点击该链接可以获得密码和修改密码.但是,最开始,你会发现,等半天都没有收到邮件,再等到猴年马月也不会收到. 但是 ...
- python基础学习笔记——开发规范
> 编码 1 2 3 4 5 所有的 Python 脚本文件都应在文件头标上 # -*- coding:utf-8 -*- 用于设置编辑器,默认保存为 utf-8 格式. > 注释 ...
- PYDay1-洗剑
学习语言的阶段: 第一阶段:所有东西都是新的::一个月 第二阶段:开始懂一些::一个月 第三阶段:感觉自己是不可战胜的:第三~第四个月 第四阶段:突然感觉什么都不知道,开发是无止境的::培训阶段不会遇 ...
- 四、harbor实践之初识harbor
1 什么是Harbor harbor是VMware公司开源的企业级Registry项目,其的目标是帮助用户迅速搭建一个企业级的Docker registry 服务. 2 什么是Registry Reg ...
- 脑阔疼的双层SQLserver游标
本来简单的双层游标没啥的,内层游标需要读取的是视图的内容,一直报“当前命令发生了严重错误.应放弃任何可能产生的结果.”的错误.无可奈何尝试先将视图的数据放到表变量中,之后再用游标遍历表变量. 简直很怀 ...