SGU 176 【带上下界的有源汇的最小流】
---恢复内容开始---
题意:
给了n个点,m条有向边。
接下来m行,每条边给起点终点与容量,以及一个标记。
标记为1则该边必须满容量,0表示可以在容量范围内任意流。
求:
从源点1号点到终点n号点的最小的可行流。
思路:
======================================================ge
1.二分最小可行流【是复杂度偏高的一种】
《一种简易的方法求解流量有上下界的网络中的网络流问题》
我自己的东西只有在二分的时候。判断当前枚举的值是偏大还是偏小其实是1号点与附加源点或者附加汇点的边的容量来看的。
坑点:
SGU的PE都是骗人的,很多WA的情况会显示成PE。大家不要被骗==
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<string.h>
#include<vector>
#define MAXN 4050
#define MAXM 40050
using namespace std;
const int inf=0x3f3f3f3f;
vector<pair<pair<int,int>,pair<int,int> > >jilu;
int inme[],outme[],n;
struct Edge
{
int v,c,f,nx;
Edge() {}
Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
} E[MAXM];
int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],sz;
void init()
{
sz=;
memset(G,-,sizeof(G));
}
void add_edge(int u,int v,int c)
{
E[sz]=Edge(v,c,,G[u]);
G[u]=sz++;
E[sz]=Edge(u,,,G[v]);
G[v]=sz++;
}
bool bfs(int S,int T)
{
static int Q[MAXN];
memset(dis,-,sizeof(dis));
dis[S]=;
Q[]=S;
for (int h=,t=,u,v,it; h<t; ++h)
{
for (u=Q[h],it=G[u]; ~it; it=E[it].nx)
{
if (dis[v=E[it].v]==-&&E[it].c>E[it].f)
{
dis[v]=dis[u]+;
Q[t++]=v;
}
}
}
return dis[T]!=-;
}
int dfs(int u,int T,int low)
{
if (u==T) return low;
int ret=,tmp,v;
for (int &it=cur[u]; ~it&&ret<low; it=E[it].nx)
{
if (dis[v=E[it].v]==dis[u]+&&E[it].c>E[it].f)
{
if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
{
ret+=tmp;
E[it].f+=tmp;
E[it^].f-=tmp;
}
}
}
if (!ret) dis[u]=-;
return ret;
}
int dinic(int S,int T)
{
int maxflow=,tmp;
while (bfs(S,T))
{
memcpy(cur,G,sizeof(G));
while (tmp=dfs(S,T,inf)) maxflow+=tmp;
}
return maxflow;
}
int check(){
bool ok=;
memcpy(cur,G,sizeof(G));
for(int i=;i<=n;i++){
if(ok==)break;
if(inme[i]-outme[i]>=){
for (int it=cur[]; ~it; it=E[it].nx){
int v=E[it].v;
if(v==i){
if(E[it].f!=E[it].c){
ok=;
}
break;
}
}
}
else{
for(int it=cur[i];~it;it=E[it].nx){
int v=E[it].v;
if(v==n+){
if(E[it].f!=E[it].c){
ok=;
}
break;
}
}
}
}
if(ok)return ;
if(inme[]>=outme[])
for(int it=cur[];~it;it=E[it].nx){
int v=E[it].v;
if(v==){
if(E[it].f==E[it].c){
return -;
}
else{
return ;
}
}
}
else
for(int it=cur[];~it;it=E[it].nx){
int v=E[it].v;
if(v==n+){
if(E[it].f==E[it].c){
return ;
}
else{
return -;
}
}
}
}
int main()
{
int m,sum1=,sum2=;
scanf("%d%d",&n,&m);
int a,b,c,d;
for(int i=;i<=m;i++){
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a==)sum1+=c;
if(b==n)sum2+=c;
if(d)d=c;
inme[b]+=d;
outme[a]+=d;
jilu.push_back(make_pair(make_pair(a,b),make_pair(c,d)));
}
int l=,r=;
while(l<=r){
init();
int mid=(l+r)>>;
inme[]+=mid;
outme[n]+=mid;
for(int i=;i<m;i++){
a=jilu[i].first.first;
b=jilu[i].first.second;
c=jilu[i].second.first;
d=jilu[i].second.second;
add_edge(a,b,c-d);
}
for(int i=;i<=n;i++){
if(inme[i]>=outme[i]){
add_edge(,i,inme[i]-outme[i]);
}
else{
add_edge(i,n+,outme[i]-inme[i]);
}
}
dinic(,n+);
if(check()>=)r=mid-;
else l=mid+;
inme[]-=mid;
outme[n]-=mid;
}
init();
inme[]+=l;
outme[n]+=l;
for(int i=;i<m;i++){
a=jilu[i].first.first;
b=jilu[i].first.second;
c=jilu[i].second.first;
d=jilu[i].second.second;
add_edge(a,b,c-d);
}
for(int i=;i<=n;i++){
if(inme[i]>=outme[i]){
add_edge(,i,inme[i]-outme[i]);
}
else{
add_edge(i,n+,outme[i]-inme[i]);
}
}
dinic(,n+);
if(check()==){
printf("%d\n",l);
memcpy(cur,G,sizeof(G));
for(int i=;i<m;i++){
int u=jilu[i].first.first;
int v=jilu[i].first.second;
int c=jilu[i].second.second;
for(int it=cur[u];~it;it=E[it].nx){
if(E[it].v==v){
printf("%d",E[it].f+c);
if(i!=m-)printf(" ");
break;
}
}
}
printf("\n");
}
else{
puts("Impossible");
}
return ;
}
---恢复内容结束---
SGU 176 【带上下界的有源汇的最小流】的更多相关文章
- SGU 194 【带上下界的无源汇的可行流】
题意: 给点数n和边数m. 接下来m条有向边. a b c d 一次代表起点终点,下界上界. 求: 判断是否存在可行流,若存在则输出某可行流.否则输出IMPOSSIBLE 思路: <一种简易的方 ...
- [BZOJ3698]XWW的难题解题报告|上下界网络流|有源汇最大流
XWW是个影响力很大的人,他有很多的追随者.这些追随者都想要加入XWW教成为XWW的教徒.但是这并不容易,需要通过XWW的考核.XWW给你出了这么一个难题:XWW给你一个N*N的正实数矩阵A,满足XW ...
- Cogs 12. 运输问题2(有上下界的有源汇最大流)
运输问题2 ★★☆ 输入文件:maxflowb.in 输出文件:maxflowb.out 简单对比 时间限制:1 s 内存限制:128 MB 运输问题 [问题描述] 一个工厂每天生产若干商品,需运输到 ...
- [ZOJ2341]Reactor Cooling解题报告|带上下界的网络流|无源汇的可行流
Reactor Cooling The terrorist group leaded by a well known international terrorist Ben Bladen is bul ...
- Shoot the Bullet(有源汇带上下界最大流)
有源汇带上下界最大流 在原图基础上连一条汇点到源点流量为inf的边,将有源汇网络流转化为无源汇网络流用相同方法判断是否满流,如果满流再跑一边源点到汇点的最大流就是答案 例题:Shoot the Bul ...
- 【HDU 4940】Destroy Transportation system(无源无汇带上下界可行流)
Description Tom is a commander, his task is destroying his enemy’s transportation system. Let’s repr ...
- ZOJ 2314 带上下界的可行流
对于无源汇问题,方法有两种. 1 从边的角度来处理. 新建超级源汇, 对于每一条有下界的边,x->y, 建立有向边 超级源->y ,容量为x->y下界,建立有向边 x-> 超级 ...
- BZOJ2150 部落战争 【带上下界最小流】
题目链接 BZOJ2150 题解 复习: 带上下界网络流两种写法: 不建\(T->S\)的\(INF\)的边,即不考虑源汇点,先求出此时超级源汇的最大流,即无源汇下最大的自我调整,再加入该边,求 ...
- uoj132/BZOJ4200/洛谷P2304 [Noi2015]小园丁与老司机 【dp + 带上下界网络流】
题目链接 uoj132 题解 真是一道大码题,,,肝了一个上午 老司机的部分是一个\(dp\),观察点是按\(y\)分层的,而且按每层点的上限来看可以使用\(O(nd)\)的\(dp\),其中\(d\ ...
随机推荐
- (委托事件处理)关于多线程执行显示进度条的实例(转)&&线程间操作无效: 从不是创建控件“rtxtEntryNO”的线程访问它。
关于多线程执行显示进度条的实例! 之前回答了一篇关于怎么在线程中操作进度条的帖子,估计有人看的不是很明白今天没事,写了一个小小的实例,很简单,就2个文件权当抛砖引玉,希望有更好解决方案的人发表一下意见 ...
- Hive(一):架构及知识体系
Hive是一个基于Hadoop的数据仓库,最初由Facebook提供,使用HQL作为查询接口.HDFS作为存储底层.mapReduce作为执行层,设计目的是让SQL技能良好,但Java技能较弱的分析师 ...
- C# .net 最大HTTP连接数
说明:本WCF程序收到请求时会对外HTTP请求. 桌面系统默认是2个,如果是SERVER,默认是10个,超过10个就会排队,当有大量向外请求时,很多对外请求就会超时.排队的HTTP请求超时仍在计时. ...
- 剑指offer系列50--不用加减乘除做加法
[题目]写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号 * [思路]1 不计进位,直接位运算(异或方式可实现此运算,即1+0 0+1为1,0+0 1+1位0) * 2 与 ...
- RabbitMQ和Kafka
转自通九大神的博客 起因 最近公司RabbitMQ的集群出了点问题,然后有些亲就说RabbitMQ慢且不好用,是一个瓶颈,不如换成Kafka.而我本人,使用RabbitMQ有一点久了,认为这个事情应当 ...
- 【maven】之使用jetty发布web项目
<plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin ...
- c++中的peek函数
c++中 cin.peek()函数 其返回值是一个char型的字符,返回值是指针指向的当前字符, 但是只是观测,指针任停留在当前位置,并不后移.如果要访问的字符是文件结束符,则函数值是EOF(-1); ...
- DBA_Oracle Sort排序处理空间耗用(概念)
2014-12-18 Created By BaoXinjian
- CE_现金模组基本概念(概念)
2014-07-12 Created By BaoXinjian
- hdu 1536 S-Nim(sg函数模板)
转载自:http://blog.csdn.net/sr_19930829/article/details/23446173 解题思路: 这个题折腾了两三天,参考了两个模板,在这之间折腾过来折腾过去,终 ...