【LA11248 训练指南】网络扩容【最大流】
题意:
给定一个有向网络,每条边均有一个容量。问是否存在一个从点1到点N,流量为C的流。如果不存在,是否可以恰好修改一条弧的容量,使得存在这样的流?
分析:
先跑一遍最大流,如果最大流大于等于C,则输possible。如果最大流小于C,则表明需要修改边的流量。很显然,需要修改的弧一定是满流的弧。但是如果直接暴力会超时,所以我们可以有两个优化。
1.第一次求完最大流以后,把每条弧的流量保存下来,每次修改完一条弧的容量以后,都从当前残量网络开始继续增广。
2.每次不需要增广到最大流,当流量大于等于C的时候就停止增广(不过不加这个优化好像也没事,反正我没加··)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector> using namespace std;
const int maxn=+;
const int maxm=+;
const int INF=;
struct Dinic{
int head[maxn],Next[maxm],to[maxm],from[maxm],cap[maxm],flow[maxm];
int n,m,s,t,sz;
bool vis[maxn];
int d[maxn],cur[maxn];
void init(int n){
this->n=n;
sz=-;
memset(head,-,sizeof(head));
}
void add_edge(int a,int b,int c){
++sz;
to[sz]=b;Next[sz]=head[a];head[a]=sz;
cap[sz]=c;flow[sz]=,from[sz]=a;;
++sz;
to[sz]=a;Next[sz]=head[b];head[b]=sz;
cap[sz]=c;flow[sz]=c,from[sz]=b;
}
bool BFS(){
memset(vis,,sizeof(vis));
for(int i=;i<=n;i++)d[i]=INF;
queue<int>Q;
d[s]=,vis[s]=;
Q.push(s);
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=head[u];i!=-;i=Next[i]){
int v=to[i];
if(cap[i]>flow[i]&&!vis[v]){
vis[v]=;
d[v]=d[u]+;
Q.push(v);
}
}
}
return vis[t];
}
int DFS(int x,int a){
if(x==t||a==)return a;
int Flow=,f;
for(int& i=cur[x];i!=-;i=Next[i]){
int v=to[i];
if(d[v]==d[x]+&&(f=DFS(v,min(a,cap[i]-flow[i])))>){
Flow+=f;
flow[i]+=f;
flow[i^]-=f;
a-=f;
if(a==)break;
}
}
return Flow;
}
int Maxflow(int s,int t){
this->s=s;this->t=t;
int Flow=;
while(BFS()){
for(int i=;i<=n;i++)cur[i]=head[i];
Flow+=DFS(s,INF);
}
return Flow;
}
}dinic;
struct Edge{
int from,to;
bool operator <(const Edge& rhs)const{
return from<rhs.from||(from==rhs.from&&to<rhs.to);
}
};
vector<Edge>ans;
int kase,N,E,C;
int main(){
kase=;
while(scanf("%d%d%d",&N,&E,&C)!=EOF&&(N||E||C)){
++kase;
printf("Case %d: ",kase);
ans.clear();
dinic.init(N);
int u,v,c;
for(int i=;i<=E;i++){
scanf("%d%d%d",&u,&v,&c);
dinic.add_edge(u,v,c);
}
int Maxflow=dinic.Maxflow(,N);
if(Maxflow>=C){
printf("possible\n");
}else{
int FLOW[maxm];
for(int i=;i<=dinic.sz;i++){
FLOW[i]=dinic.flow[i];
}
int CAP,c=C-Maxflow;
for(int i=;i<=dinic.sz;i+=){
if(dinic.cap[i]==dinic.flow[i]){ for(int i=;i<=dinic.sz;i++)dinic.flow[i]=FLOW[i];
CAP=dinic.cap[i];
dinic.cap[i]=C;
dinic.cap[i^]=C;
Maxflow=dinic.Maxflow(,N);
if(Maxflow>=c){
ans.push_back((Edge){dinic.from[i],dinic.to[i]});
}
dinic.cap[i]=CAP;
dinic.cap[i^]=CAP;
for(int i=;i<=dinic.sz;i++)dinic.flow[i]=FLOW[i];
}
}
if(ans.size()==){
printf("not possible\n");
}else{
sort(ans.begin(),ans.end());
printf("possible option:");
for(int i=;i<ans.size();i++){
if(i!=)printf(",");
printf("(%d,%d)",ans[i].from,ans[i].to);
}
printf("\n");
}
}
}
return ;
}
【LA11248 训练指南】网络扩容【最大流】的更多相关文章
- BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)
第一问直接跑最大流.然后将所有边再加一次,费用为扩容费用,容量为k,再从一个超级源点连一条容量为k,费用为0的边到原源点,从原汇点连一条同样的边到超级汇点,然 后跑最小费用最大流就OK了. ---- ...
- 【BZOJ1834】[ZJOI2010]network 网络扩容 最大流+最小费用流
[BZOJ1834][ZJOI2010]network 网络扩容 Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不 ...
- bzoj 1834: [ZJOI2010]network 网络扩容 -- 最大流+费用流
1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec Memory Limit: 64 MB Description 给定一张有向图,每条边都有一个容量C和一 ...
- [BZOJ1834][ZJOI2010]network 网络扩容 最大流+费用流
1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec Memory Limit: 64 MB Submit: 3330 Solved: 1739 [Subm ...
- BZOJ 1834 网络扩容 最大流+最小费用流
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1834 题目大意: 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是 ...
- [ZJOI2010][bzoj1834] 网络扩容 [费用流]
题面 传送门 思路 第一问:无脑网络流跑一波 第二问: 先考虑一个贪心的结论:扩容出来的扩容流量一定要跑满 证明显然 因此我们可以把扩容费用可以换个角度思考,变成增加一点流量,花费W的费用 这样,我们 ...
- bzoj1834: [ZJOI2010]network 网络扩容 费用流
bzoj1834 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1.在不扩容的情况下,1到N的最大流: 2.将1到N的最大流增加K所需的最小扩容 ...
- BZOJ 1834 网络扩容(最大流+费用流)
对于第一问,直接求最大流. 对于第二问,建源点s和汇点t,s连1容量为INF,费用为0的边,n连t容量为最大流+k,费用为0的边.这样就把最大流限制为最多增加k了. 限制需要求扩充的最小费用,原图的边 ...
- BZOJ-1834 网络扩容 最小费用最大流+最大流+乱搞
1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec Memory Limit: 64 MB Submit: 2269 Solved: 1136 [Submit ...
随机推荐
- functool.wraps and functools.partial
functools.partial 通过包装手法,允许我们 "重新定义" 函数签名. 通常是将函数的部分参数给固定下来, 从而形成一个输入参数更少的新函数. functool.w ...
- k8s helm 私服chartmuseum minio s3 存储配置
1. 安装minio 使用docker 安装 参考项目 https://github.com/rongfengliang/mino-thumbor-openresty 备注: 因为是一个集成项目可能会 ...
- CRC 自动判断大端 小端
/* aos_crc64.c -- compute CRC-64 * Copyright (C) 2013 Mark Adler * Version 1.4 16 Dec 2013 Mark Adle ...
- Java将对象写入文件读出——序列化与反序列化
Java类中对象的序列化工作是通过ObjectOutputStream和ObjectInputStream来完成的. 写入: File aFile=new File("e:\\c.txt&q ...
- 适配:px与dp转换
public class DensityUtil { /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ public static int dip2px(Context con ...
- java------------break;
总结: package com.mmm; public class Pnal { public static void main(String[] args) { int i = 0; while ( ...
- Linux系统启动流程与系统目录
启动流程 # 1,开机BIOS自检 检查一系列的硬件,最后根据启动顺序启动,是硬盘还是光驱等 # 2,MBR引导 读硬盘0柱面0磁道1扇区的前446字节 1扇区=512字节 MBR=4446字节 四个 ...
- 十三 Thread的一些常用方法
setName() : 给线程起名字. isAlive() : 线程是否存或. currentThread() : 取得当前线程. getId() : 取得线程的唯一标识.
- Apache 的编译安装
直接看步骤: 1.安装必备环境:gcc.pcre .................................. 2.安装apr.apr-util 3.解压编译安装Apache: ./confi ...
- OD 界面简介
1 为汇编代码对应的地址窗口 2 为汇编代码对应的十六进制机器码窗口 3 为反汇编窗口 4 为反汇编代码对应的注释信息窗口 5 为寄存器信息窗口 6 为当前执行到的反汇编代码的信息窗口 7~9 为数据 ...