网络流例题学习2

有点长…分个P好了

人民群众喜闻乐见的网络流24题 http://cojs.tk/cogs/problem/index.php?key=%E7%BD%91%E7%BB%9C%E6%B5%8124%E9%A2%98

搭配飞行员

二分图最大匹配裸题

如果要强行上最大流…那么就S->左边每一个点连边容量1,该连的边连一下容量1,右边每一个点->T连边容量1

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
int n,fst[233333],nxt[233333],vb[233333],M=0,match[233333];
void ad_dl(int a,int b) {++M; nxt[M]=fst[a]; fst[a]=M; vb[M]=b;}
void addl(int a,int b) {ad_dl(a,b); ad_dl(b,a);}
bool vis[233333];
bool find(int x)
{
    for(int e=fst[x];e;e=nxt[e])
    {
        int b=vb[e];
        if(vis[b]) continue;
        vis[b]=1;
        if(!match[b]||find(match[b]))
        {
            match[b]=x; match[x]=b; return 1;
        }
    }
    return 0;
}
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
int main()
{
    FO(flyer)
    int n1;
    scanf("%d%d",&n,&n1);
    int a,b;
    while(scanf("%d%d",&a,&b)!=EOF) addl(a,b);
    int ans=0;
    for(int i=1;i<=n1;i++)
    {
        for(int j=1;j<=n;j++) match[j]=0;
        if(find(i)) ++ans;
    }
    printf("%d",ans);
}
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
#define SZ 233333
int n,M=1;typedef long long ll;
int fst[SZ],nxt[SZ],vb[SZ],cap[SZ];
void _ad_dl(int a,int b,int c) {++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;cap[M]=c;}
void ad_dl(int a,int b,int c) {_ad_dl(a,b,c); _ad_dl(b,a,0);}
int S,T,q[SZ],d[SZ];
bool bfs()
{
    memset(d,-1,sizeof(d));
    d[S]=0; q[1]=S; int h=1,t=2;
    while(h!=t)
    {
        int cur=q[h++];
        for(int e=fst[cur];e;e=nxt[e])
        {
            int b=vb[e];
            if(d[b]==-1&&cap[e]) d[b]=d[cur]+1, q[t++]=b;
        }
    }
    return d[T]!=-1;
}
int dfs(int x,int f)
{
    if(f<=0) return 0;
    if(x==T) return f;
    int ca=0;
    for(int e=fst[x];e;e=nxt[e])
    {
        int b=vb[e];
        if(d[b]!=d[x]+1) continue;
        int w=dfs(b,min(cap[e],f-ca));
        cap[e]-=w; cap[e^1]+=w; ca+=w;
        if(ca==f) break;
    }
    if(!ca) d[x]=-1;
    return ca;
}
#define inf 1000000000
int dinic()
{
    int ans=0;
    while(bfs()) ans+=dfs(S,inf);
    return ans;
}
//=============以上均为模板=============
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
int main()
{
    FO(flyer)
    int n1;
    scanf("%d%d",&n,&n1);
    int a,b; S=n+1; T=n+2;
    while(scanf("%d%d",&a,&b)!=EOF) ad_dl(a,b,1), ad_dl(b,a,1);
    for(int i=1;i<=n1;i++) ad_dl(S,i,1);
    for(int i=n1+1;i<=n;i++) ad_dl(i,T,1);
    n+=2; printf("%d\n",dinic());
}

太空飞行计划

最大权闭合子图的裸题

有向图的闭合图:闭合图内任意点的任意后继也一定还在闭合图中。

(以上两张图截自2007《最小割模型在信息学竞赛中的应用》Amber)

那这题我们把每一个仪器的点权设为-费用,实验点权设为收益,然后实验->仪器加边,这样就是要求一个点权最大的闭合子图。

转化成最小割:加一个源汇,源->正权点容量为点权,负权点->汇容量为-点权,原来的边容量为∞。然后只要选S割集的点就是最大权闭合子图,最大权值就是正权之和-最大流。

最小割=最大流这不用说吧。最小割的方案对于最大流来说只要从S开始在残余网络上bfs,能bfs到的是一个割集。

所以就是道大水题啦~

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
#define SZ 233333
int n,M=1;typedef long long ll;
int fst[SZ],nxt[SZ],vb[SZ],cap[SZ];
void _ad_dl(int a,int b,int c) {++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;cap[M]=c;}
void ad_dl(int a,int b,int c) {_ad_dl(a,b,c); _ad_dl(b,a,0);}
int S,T,q[SZ],d[SZ];
bool bfs()
{
    memset(d,-1,sizeof(d));
    d[S]=0; q[1]=S; int h=1,t=2;
    while(h!=t)
    {
        int cur=q[h++];
        for(int e=fst[cur];e;e=nxt[e])
        {
            int b=vb[e];
            if(d[b]==-1&&cap[e]) d[b]=d[cur]+1, q[t++]=b;
        }
    }
    return d[T]!=-1;
}
int dfs(int x,int f)
{
    if(f<=0) return 0;
    if(x==T) return f;
    int ca=0;
    for(int e=fst[x];e;e=nxt[e])
    {
        int b=vb[e];
        if(d[b]!=d[x]+1) continue;
        int w=dfs(b,min(cap[e],f-ca));
        cap[e]-=w; cap[e^1]+=w; ca+=w;
        if(ca==f) break;
    }
    if(!ca) d[x]=-1;
    return ca;
}
#define inf 1000000000
int dinic()
{
    int ans=0;
    while(bfs()) ans+=dfs(S,inf);
    return ans;
}
//=============以上均为模板=============
int C[233333],P[233333];
char buf[2333333];
bool vis[2333333];
bool gj[2333333];
void bfs_2()
{
    int h=1,t=2; q[1]=S; gj[S]=1;
    while(h!=t)
    {
        int cur=q[h++];
        for(int e=fst[cur];e;e=nxt[e])
        {
            int b=vb[e];
            if(cap[e]&&!gj[b]) q[t++]=b, gj[b]=1;
        }
    }
}
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
int main()
{
    FO(shuttle)
    int tot=0,M,N; scanf("%d%d\n",&M,&N);
    n=M+N+2; S=n-1; T=n;
    for(int i=1;i<=M;i++)
    {
        scanf("%d",P+i);
        tot+=P[i];
        ad_dl(S,i,P[i]);
        for(;;)
        {
            char c;
            do c=getchar(); while (c==‘ ‘);
            ungetc(c,stdin);
            if (c==10 || c==13) break;
            int x;
            scanf("%d",&x);
            ad_dl(i,x+M,1000000000);
        }
    }
    for(int i=1;i<=N;i++)
    {
        scanf("%d",C+i);
        ad_dl(i+M,T,C[i]);
    }
    int ans=dinic(); bfs_2();
    int f1=0;
    for(int i=1;i<=M;i++) if(gj[i])
    {
        if(f1) putchar(‘ ‘); else f1=1;
        printf("%d",i);
    }
    f1=0;
    putchar(10);
    for(int i=1;i<=N;i++) if(gj[i+M])
    {
        if(f1) putchar(‘ ‘); else f1=1;
        printf("%d",i);
    }
    putchar(10);
    printf("%d\n",tot-ans);
}

这题输入较为捉鸡,然后去看std,get了一个新函数叫ungetc,就是把一个字符退回到输入流…(╯‵□′)╯为什么我原来不知道有这种神奇的函数

时间: 2024-10-25 23:18:37

网络流例题学习2的相关文章

网络流例题学习

之前似乎网络流的建图题做得比较少啊-现在来做一点. 首先是模板. poj1273 草地排水 #include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <vector> #include <limits> #include <set> #include &

【CodeVS 1993】草地排水 isap模板题

开始网络流的学习,更新一下isap的模板 #include<cstdio> #include<cstring> #include<algorithm> #define read(x) x=getint() using namespace std; const int N = 403; int getint() { int k = 0, fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getc

ZOJ 3229 Shoot the Bullet 有源有汇带下界的最大流

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3229 Shoot the Bullet Time Limit: 2 Seconds      Memory Limit: 32768 KB      Special Judge Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a u

poj3189 Steady Cow Assignment --- 多重匹配,二分图匹配解法

有n头牛,m个牛棚,每头牛对牛棚的满意程度有一个排序,每个牛棚有牛数限制. 问如何分配各个牛,使得所有牛的满意程度的差值最小. 这题首先可以想到二分答案,对于每一种差值来求是否可行. 不想再搞网络流,学习了下二分图匈牙利解法.. 匹配时,对于每一种选择(牛棚),若满足范围,且有多余的容量,则匹配: 否则,对于该牛棚已经匹配过的牛进行增广. #include <iostream> #include <cstdlib> #include <cstring> #include

《网络流学习笔记01--HDU3549》

1.网络流初步. 网络流是一个适用范围相当广泛的模型,相关的算法也很多,这里就几天学习网络流的相关知识做一个总结归纳. (1)最大流问题 如图所示,假设你需要把一些物品从结点s(称为源点)运送到结点t(称为汇点),可以从其他结点中转,图(a)中各条有向边的权表示最多能有多少个物品从这条边的起点直接运送到终点,例如图(a)从结点V3到V2最多可以运送9个物品. 图(b)给出了一种可能的最优方案,其中每条边中的第一个数字表示实际运送的物品数量,第二个数字表示题目中的上限, 我们把求解这样的问题称为最

学渣乱搞系列之网络流学习

学渣乱搞系列之网络流学习 几篇优秀的文章,鉴于本学渣目前功力不够,还不能掌握网络流的精髓要义.故载几篇牛文. Dinic算法: Comzyh的博客 Lich_Amnesia

【网络流#6】POJ 3041 Asteroids 二分图最大匹配 - 《挑战程序设计竞赛》例题

学习网络流中ing...作为初学者练习是不可少的~~~构图方法因为书上很详细了,所以就简单说一说 把光束作为图的顶点,小行星当做连接顶点的边,建图,由于 最小顶点覆盖 等于 二分图最大匹配 ,因此求二分图最大匹配即可. 邻接矩阵,DFS寻找增广路,匈牙利算法 邻接矩阵:复杂度O(n^3) 如果使用邻接表:复杂度O(n*m) #include<cstdio> #include<cstring> #include<cmath> #include<iostream>

hdu3342(Legal or Not)----- 学习拓扑排序的好例题

经典拓扑排序 点击打开链接 Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is so harmonious that just like a big family. Every day,many "holy cows" like HH, hh, AC, ZT, lcc, BF, Qinz and so on chat on-line to exch

hihoCoder 1394 : 网络流四&#183;最小路径覆盖 (网络流学习#4 记录)

题目链接:http://hihocoder.com/problemset/problem/1394 代码: #include<bits/stdc++.h> using namespace std; const int N=505*2+10,M=20005,INF=0x3f3f3f3f; int n,m; int c[N][N],pre[N]; int s,t; int bfs() { memset(pre,0,sizeof(pre)); queue<int>q; q.push(s)