网络流入门 洛谷P1231

第一道自己写的网络流的题,\(^o^)/~。虽然改了好久但终于还是改出来了,其实bug不过两个:1数组开小了;

2没有将点分割开导致经过一个点的流超过1;

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define inf ~0u>>1
#define maxm 500050
#define maxn 500050
using namespace std;
inline void read(int &x){
    char ch;
    bool flag=false;
    for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
    for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=flag?-x:x;
}
inline void write(int x){
    static const int maxlen=100;
    static char s[maxlen];
        if (x<0)	{	putchar('-'); x=-x;}
    if(!x){ putchar('0'); return; }
    int len=0; for(;x;x/=10) s[len++]=x % 10+'0';
    for(int i=len-1;i>=0;--i) putchar(s[i]);
}
int deep[maxn];
int v[maxm],pre[maxm],son[maxm],now[maxn],tot,st[maxm];
int n,m;
int n1,n2,n3,m1,m2;
bool use[maxm];

int d[maxn],t,w;
bool bfs(){
memset(deep,-1,sizeof(deep));
t=1;w=1;d[1]=0; deep[0]=0;
while (t<=w)
	{
		int x=d[t];
		for (int p=now[x];p;p=pre[p])
			if (deep[son[p]]<0)
				if (v[p])
				{
					int y=son[p];
					deep[y]=deep[x]+1;
					d[++w]=y;
					if (y==n)
					 {
						return 1;
					 }
				}
		++t;
	}
return 0;
}



int dfs(int x,int Min){
if (x==n)	return Min;
int ans=0; 
for (int p=now[x];p;p=pre[p])
	if (v[p] && deep[x]<deep[son[p]])
		{
			int tmp=dfs(son[p],min(Min,v[p]));
			v[p]-=tmp; v[p^1]+=tmp;
			Min-=tmp;	ans+=tmp;
			if (tmp)
				{
					use[p]=1;
					use[p^1]=0;
				}
			if (Min==0)
					return ans;
		}
deep[x]=-1;
return ans;
}

void build(int a,int b,int c){
pre[++tot]=now[a];
now[a]=tot;
st[tot]=a;
son[tot]=b;
v[tot]=c;
}


int main(){
memset(use,0,sizeof(use));
scanf("%d%d%d",&n1,&n2,&n3);
n=n1+n2+n3+1+n1;

tot=1;
for (int i=n1+1;i<=n1+n2;i++)
	{
		build(0,i,1);
		build(i,0,0);
	}
for (int i=n1+n2+1;i<=n1+n2+n3;i++)
	{
		build(n,i,0);
		build(i,n,1);
	}	
for (int i=1;i<=n1;i++)
	{
		build(n1+n2+n3+i,i,0);
		build(i,n1+n2+n3+i,1);
	}
scanf("%d",&m1);
for (int i=1;i<=m1;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		b+=n1;
		build(b,a,1);
		build(a,b,0);
	}
scanf("%d",&m2);
for (int i=1;i<=m2;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		a+=n1+n2+n3; b+=n1+n2;
		build(a,b,1);
		build(b,a,0);
	}
int sum=0;
for (;bfs();sum+=dfs(0,inf));
printf("%d\n",sum);
return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值