首页 > 其他分享 >网络流杂题选做

网络流杂题选做

时间:2023-05-25 21:56:46浏览次数:35  
标签:int res flow 网络 write dep 流杂题 define

最近总是不知不觉地就做到了网络流的题,感觉知识树要点偏。算了,先随便写点东西再说。

[AHOI2009]最小割

题面

显然一条边至少要满流才有可能是被割边。

先考虑存在性问题,若一条边为某个最小割割边集中的边,那么这条边一定是该最小割中无法取代的。对于一条流量为 \(0\) 的边 \((u,v)\),如果在残量网络上存在从 \(u\) 到 \(v\) 的路径,即在残量网络上 \(u,v\) 属于同一连通块(因为 \((v,u)\) 这条边必然在残量网络中),那么可以从这条路径中分点流量到另一条路径,就不存在一个最小代价路径切断方案,其中该道路被切断。

再考虑必要性问题,先给出结论,当且仅当 \(u\) 和 \(S\) 在同一强连通分量中,同时 \(v\) 和 \(T\) 在同一强连通分量中。因为一条边如果没满流,那么残量网络上必然同时存在原边和反边,两端点同属一强连通分量。考虑缩点后的 DAG,从 \(S\) 到 \(T\) 的路径上如果有不止一条边,那么没有一条边是必然被切断的。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
            }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=1e4+10,M=1e5+10,inf=INT_MAX;
int n,m,S,T,tot=1,head[N];
struct edge{
    int u,v,nxt,w;
}e[M<<2];
void add(int u,int v,int w){
    e[++tot].v=v;
    e[tot].u=u;
    e[tot].w=w;
    e[tot].nxt=head[u];
    head[u]=tot;
}
int dep[N],cur[N];
bool bfs(int S,int T){
    for(int i=1;i<=n;i++){
        dep[i]=0;
    }
    dep[S]=1;
    queue<int>q;
    q.push(S);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v,w=e[i].w;
            if(!dep[v]&&w){
                dep[v]=dep[u]+1;
                if(v==T){
                    return 1;
                }
                q.push(v);
            }
        }
    }
    return 0;
}
int dfs(int u,int flow,int T){
    if(u==T){
        return flow;
    }
    int s=0;
    for(int i=cur[u];i;i=e[i].nxt){
        cur[u]=i;
        int v=e[i].v,w=e[i].w;
        if(dep[v]==dep[u]+1&&w){
            int res=dfs(v,min(flow,w),T);
            s+=res;
            flow-=res;
            e[i].w-=res;
            e[i^1].w+=res;
        }
        if(!flow){
            break;
        }
    }
    if(!s){
        dep[u]=0;
    }
    return s;
}
int dfn[N],low[N],col[N],idx,col_num,stk[N],top,in_stack[N];
void tarjan(int u){
    low[u]=dfn[u]=++idx;
    stk[++top]=u;
    in_stack[u]=1;
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].v,w=e[i].w;
        if(!w){
            continue;
        }
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(in_stack[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        col[u]=++col_num;
        in_stack[u]=0;
        while(stk[top]!=u){
            col[stk[top]]=col_num;
            in_stack[stk[top]]=0;
            top--;
        }
        top--;
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    read(n),read(m),read(S),read(T);
    for(int i=1;i<=m;i++){
        int u,v,w;
        read(u),read(v),read(w);
        add(u,v,w);
        add(v,u,0);
    }
    while(bfs(S,T)){
        for(int i=1;i<=n;i++){
            cur[i]=head[i];
        }
        dfs(S,inf,T);
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i]){
            tarjan(i);
        }
    }
    for(int i=1;i<=m;i++){
        if(!e[i<<1].w){
            int u=e[i<<1].u,v=e[i<<1].v;
            if(col[u]!=col[v]){
                write_space(1);
            }
            else{
                write_space(0);
            }
            if(col[u]==col[S]&&col[v]==col[T]){
                write_endl(1);
            }
            else{
                write_endl(0);
            }
        }
        else{
            puts("0 0");
        }
    }
    return 0;
}

[NOI2009] 植物大战僵尸

题面

我们将一个植物前面的植物视作也保护它的植物。因为要击溃一个植物,必须击溃保护它的植物。所以,从保护的植物连边到被保护的植物。但是可能有环,环上的植物是不可能被击溃,所以做一遍拓扑排序,只有被遍历过的植物才有可能是被击溃的植物。我们只保留遍历过的植物,和边上的两个植物都遍历过的边。那么最后题目就变成了求这个图的最大权闭合子图。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
            }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=610,M=1e6+10,inf=1e9 ;
int n,m,val[N];
int id(int x,int y){
    return (x-1)*m+y;
}
vector<int>G[N],out[N];
int deg[N],vis[N],S,T,tot=1,head[N],ans;
void topo(){
    queue<int>q;
    for(int i=1;i<=n*m;i++){
        if(!deg[i]){
            q.push(i);
        }
    }
    while(!q.empty()){
        int u=q.front();
        vis[u]=1;
        q.pop();
        for(auto v:G[u]){
            deg[v]--;
            if(!deg[v]){
                q.push(v);
            }
        }
    }
}
struct node{
    int v,w,nxt;
}e[M<<1];
void add(int u,int v,int w){
    e[++tot].v=v;
    e[tot].w=w;
    e[tot].nxt=head[u];
    head[u]=tot;
}
int dep[N],cur[N];
bool bfs(int S,int T){
    for(int i=1;i<=T;i++){
        dep[i]=0;
    }
    queue<int>q;
    q.push(S);
    dep[S]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v,w=e[i].w;
            if(w&&!dep[v]){
                dep[v]=dep[u]+1;
                if(v==T){
                    return 1;
                }
                q.push(v);
            }
        }
    }
    return 0;
}
int dfs(int u,int flow,int T){
    if(u==T){
        return flow;
    }
    int s=0;
    for(int i=cur[u];i;i=e[i].nxt){
        int v=e[i].v,w=e[i].w;
        if(w&&dep[v]==dep[u]+1){
            int res=dfs(v,min(flow,w),T);
            e[i].w-=res;
            e[i^1].w+=res;
            s+=res;
            flow-=res;
        }
        if(!flow){
            break;
        }
    }
    if(!s){
        dep[u]=0;
    }
    return s;
}
int dinic(int S,int T){
    int sum=0;
    while(bfs(S,T)){
        for(int i=1;i<=T;i++){
            cur[i]=head[i];
        }
        sum+=dfs(S,inf,T);
    }
    return sum;
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    read(n),read(m);
    S=n*m+1,T=n*m+2;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            read(val[id(i,j)]);
            int sum;
            read(sum);
            for(int k=1,x,y;k<=sum;k++){
                read(x),read(y);
                x++,y++;
                out[id(i,j)].pb(id(x,y));
                G[id(i,j)].pb(id(x,y));
                deg[id(x,y)]++;
            }
            if(j<m){
                out[id(i,j+1)].pb(id(i,j));
                G[id(i,j+1)].pb(id(i,j));
                deg[id(i,j)]++;
            }
        }
    }
    topo();
    for(int i=1;i<=n*m;i++){
        if(!vis[i]){
            continue;
        }
        if(val[i]>0){
            add(S,i,val[i]);
            add(i,S,0);
            ans+=val[i];
        }
        else{
            add(i,T,-val[i]);
            add(T,i,0);
        }
        for(auto x:out[i]){
            if(!vis[x]){
                continue;
            }
            add(x,i,inf);
            add(i,x,0);
        }
    }
    write_endl(ans-dinic(S,T));
    return 0;
}

[SDOI2013]费用流

题面

别看到题目叫作费用流,就一股脑写费用流了。注意到题目中有句话,Bob在分配单位花费之前,已经知道Alice所给出的最大流方案。那么Bob的赋权方法就是确定的,将所有权值赋给这个最大流方案中流量最大的边,那么题目要求的东西就变成了求最大流并求一个最大流方案,使得流量最大的边流量最小。

求最大值最小,二分最大边流量 \(x\),所有边的流量对 \(x\) 取 \(\min\)。看这样的图上的最大流是否是原图上的最大流,是则说明这个最大流量是合法,反之亦然。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
            }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=110,M=1e3+10,inf=1e9;
int head[N],tot=1,n,m,S,T,val;
double max_flow;
struct edge{
    int v,nxt;
    double W,w;
}e[M<<1];
int dep[N],cur[N];
bool bfs(int S,int T){
    for(int i=1;i<=n;i++){
        dep[i]=0;
    }
    dep[S]=1;
    queue<int>q;
    q.push(S);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            double w=e[i].w;
            if(!dep[v]&&w>eps){
                dep[v]=dep[u]+1;
                if(v==T){
                    return 1;
                }
                q.push(v);
            }
        }
    }
    return 0;
}
double dfs(int u,double flow,int T){
    if(u==T){
        return flow;
    }
    double s=0;
    for(int i=cur[u];i;i=e[i].nxt){
        cur[u]=i;
        int v=e[i].v;
        double w=e[i].w;
        if(dep[v]==dep[u]+1&&w>eps){
            double res=dfs(v,min(flow,w),T);
            e[i].w-=res;
            e[i^1].w+=res;
            flow-=res;
            s+=res;
        }
        if(flow<eps){
            break;
        }
    }
    if(!s){
        dep[u]=0;
    }
    return s;
}
double dinic(int S,int T){
    double flow=0;
    while(bfs(S,T)){
        for(int i=1;i<=n;i++){
            cur[i]=head[i];
        }
        flow+=dfs(S,inf,T);
    }
    return flow;
}
void add(int u,int v,int w){
    e[++tot].v=v;
    e[tot].W=e[tot].w=w;
    e[tot].nxt=head[u];
    head[u]=tot;
}
void add_e(int u,int v,int w){
    add(u,v,w);
    add(v,u,0);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    read(n),read(m),read(val);
    for(int i=1,u,v,w;i<=m;i++){
        read(u),read(v),read(w);
        add_e(u,v,w);
    }
    S=1,T=n;
    max_flow=dinic(S,T);
    write_endl((int)max_flow);
    ll l=0,r=5e9,ans=0;
    while(l<=r){
        ll mid=(l+r)>>1;
        for(int i=1;i<=tot;i++){
            e[i].w=min(e[i].W,1.0*mid/100000.0);
        }
        double flow=dinic(S,T);
        if(fabs(flow-max_flow)<eps){
            r=mid-1;
            ans=mid;
        }
        else{
            l=mid+1;
        }
    }
    printf("%.6lf\n",ans/100000.0*val);
    return 0;
}

标签:int,res,flow,网络,write,dep,流杂题,define
From: https://www.cnblogs.com/luoshen0/p/17396380.html

相关文章

  • Katana:一款功能强大的下一代网络爬虫框架
    关于KatanaKatana是一款功能强大的下一代网络爬虫框架,在该工具的帮助下,广大研究人员可以轻松完成资源爬取和渗透测试阶段的信息收集任务。功能介绍1、快速且完全可配置的网络资源爬取;2、支持标准模式和Headless模式;3、JavaScript解析/爬取;4、可自定义的自动化表单填充;5、范......
  • RHEL8使用iSCSI部署网络存储-Linux就这么学17
        本章首先介绍计算机硬件存储设备的不同接口的优缺点,并由此切入iSCSI技术主题的讲解。iSCSI技术实现了物理硬盘设备与TCP/IP网络协议的相互结合,使得用户能够通过互联网方便地访问远程机房提供的共享存储资源。我们将学习在Linux系统上部署iSCSI服务端程序,并分别......
  • 深度学习分类网络---ResNet
    一、为什么引入ResNet通过上一篇分类网络的介绍,我们知道网络的宽度和深度可以很好的提高网络的性能,深的网络一般都比浅的的网络效果好,但训练一个很深的网络是非常困难的,一方面是网络越深越容易出现梯度消失和梯度爆炸问题,然而这个问题通过BN层和ReLU激活函数等方法在很大程度上......
  • 网络--传输层
    seq:这一次传递数据的编号,ack:期望下一次传给自己数据的编号//三次握手1)C-->SSYN=1,seq=s1,  ACK=0,  len=02)C<--SSYN=1,seq=s2, ACK=s1+1,len=03)C-->SSYN=0,seq=s1+1,ACK=s2+1,len=0//Http请求的数据4)C-->SSYN=0,seq=s1+1,ACK=s2+1,len=k//返回的数据5)C<--SSYN=......
  • 常见的网络攻击方式
      ......
  • 计算机网络 一、什么是因特网
    什么是因特网从具体构成角度通过 通信链路 和 分组交换机 将 主机(host) 或 端系统(endsystem) 连接到一起的网络。通信链路(communicationlink) 通常指电缆、铜线、光纤等物理媒介。分组交换机 允许链路互联以形成更大规模的网络,常见的交换机如 路由器(router)......
  • 机器学习(八):贝叶斯网络——福尔摩斯推理、草地喷水器推断
    实验4贝叶斯网络一、预备知识二、实验目的掌握贝叶斯网络算法的原理及设计;掌握利用贝叶斯网络算法解决推理分析。三、实验内容福尔摩斯先生在办公室接到了他邻居华生的电话P(W=T)。华生告诉他:他的家里可能进了窃贼P(B=T),因为他家的警铃响了P(A=T)被告......
  • 500代码行代码手写docker-设置网络命名空间
    (4)500代码行代码手写docker-设置网络命名空间本系列教程主要是为了弄清楚容器化的原理,纸上得来终觉浅,绝知此事要躬行,理论始终不及动手实践来的深刻,所以这个系列会用go语言实现一个类似docker的容器化功能,最终能够容器化的运行一个进程。本章的源码已经上传到github,地址如下:......
  • 计算机网络(三)物理层
    计算机网络(三)物理层1物理层的基本概念物理层就是要解决在连接计算机的传输媒体上传输数据比特流(比特0和比特1)的问题向上一层数据链路层屏蔽各种传输媒体的差异,提供透明的比特流传输服务。物理层协议的主要任务2物理层下的传输媒体​ 传输媒体分为两类:导引型传输媒......
  • 计算机网络(二)OSI七层模型、TCPIP四层模型与原理五层模型
    1OSI参考七层模型(法律上的标准)OSI七层模型OSI:开放式互连通信参考模型分层的原因:标准化、降低各个层之间的关联依赖①应用层:能产生流量能够和用户交互的应用②表示层:加密压缩,开发人员考虑的问题③会话层:服务器和客户端建立的会话netstat-nb④传输层:进行可靠传输、不......