LOJ#101最大流

本博客由于博主太弱可能已经废了你看博主多久没更新博客肯定是天天被吊打已经没有勇气写博客了

马上就要NOI了,NOI之前我们当然应该压压代码卡卡常准备NOI零爆爆底垫垫啦(雾)

事情是这样的

下午在家无聊睡觉的我突然从梦中醒来,贴了一个Dinic和fread的板子往上一交,发现根本就没有TLE嘛,可是AC时间却是rank1的十倍,果然不愧千古神犇wxh。

如图(越卡常越慢菜鸡瑟瑟发抖)

然后蒟蒻zzt滚出家门,到了晚上八点半才回家,造了一组随机数据,由于机子比较菜发现需要17s才能跑出来(-O2),然后蒟蒻zzt表示不服,于是就有了今天的被吊打故事。

先贴一个loj上总共跑了17s的代码吧QAQ

#include"bits/stdc++.h"

using namespace std;
typedef long long ll;

namespace io{
	const int L=(1<<20)+1;
	char _buf[L],*S,*T,c;
	char gc(){
		if(S==T){
			T=(S=_buf)+fread(_buf,1,L,stdin);
			return S==T?EOF:*S++;
		}
		return*S++;
	}
	template<class T>
	void gi(T&x){
		for(c=gc();c<'0'||c>'9';c=gc());
		x=c&15;
		for(c=gc();c>='0'&&c<='9';c=gc())x=x*10+(c&15);
	}
	char obuf[L],*op=obuf,*end=obuf+(L-1);
	void writechar(char x){
		*op++=x;
		if(op==end)fwrite(obuf,1,L-1,stdout),op=obuf;
	}
	int tp;char st[25];
	template<class T>
	void print(T a){
		if(!a)writechar('0');else{
			for(tp=0;a;st[tp++]=a%10+'0',a/=10);
			for(tp--;~tp;writechar(st[tp--]));
		}
	}
	void cbuf(){
		fwrite(obuf,1,op-obuf,stdout),op=obuf;
	}
};
using io::gi;
using io::writechar;
using io::print;

const int N=1000005,M=8000005,inf=0x7FFFFFFF;
int h[N],nxt[M],to[M],flow[M],tmp=1,n,m,S,T,q[N],l,r,d[N];

void addedge(int u,int v,int f){
	to[++tmp]=v, nxt[tmp]=h[u], h[u]=tmp, flow[tmp]=f;
	to[++tmp]=u, nxt[tmp]=h[v], h[v]=tmp, flow[tmp]=0;
}

bool bfs(){
	register int i;
	memset(d,-1,(n+1)<<2);
	for(d[q[l=r=1]=S]=1;l<=r;l++)
		for(i=h[q[l]];i;i=nxt[i])
			if(d[to[i]]==-1&&flow[i])
				d[to[i]]=d[q[l]]+1,q[++r]=to[i];
	return d[T]!=-1;
}

int dfs(int x,int mf){
	if(x==T)return mf;
	register int res=0,p,i;
	for(i=h[x];i;i=nxt[i])if(d[to[i]]==d[x]+1&&flow[i]){
		p=dfs(to[i],min(mf,flow[i]));
		flow[i]-=p,flow[i^1]+=p,res+=p,mf-=p;
		if(!mf)break;
	}
	if(!res)d[x]=-1; 
	return res;
}

int main(){
	gi(n),gi(m),gi(S),gi(T);
	int u,v,c,i;
	for(i=1;i<=m;i++){
		gi(u),gi(v),gi(c);
		if(u==v||!c)continue;
		addedge(u,v,c);
	}
	ll ans=0;
	while(bfs())ans+=dfs(S,inf);
	print(ans);
	io::cbuf();
	return 0;
}

想要变快似乎需要魔改? zzt表示瑟瑟发抖并准备开始优化。

-- 半个小时后zzt改了个vector版本发现更慢了

然后zzt写了一个每次存边的版本,发现要快很多,可是似乎还是比许多dalao慢得多。

#include"bits/stdc++.h"

using namespace std;
typedef long long ll;

namespace io{
	const int L=(1<<20)+1;
	char _buf[L],*S,*T,c;
	char gc(){
		if(S==T){
			T=(S=_buf)+fread(_buf,1,L,stdin);
			return S==T?EOF:*S++;
		}
		return*S++;
	}
	template<class T>
	void gi(T&x){
		for(c=gc();c<'0'||c>'9';c=gc());
		x=c&15;
		for(c=gc();c>='0'&&c<='9';c=gc())x=x*10+(c&15);
	}
	char obuf[L],*op=obuf,*end=obuf+(L-1);
	void writechar(char x){
		*op++=x;
		if(op==end)fwrite(obuf,1,L-1,stdout),op=obuf;
	}
	int tp;char st[25];
	template<class T>
	void print(T a){
		if(!a)writechar('0');else{
			for(tp=0;a;st[tp++]=a%10+'0',a/=10);
			for(tp--;~tp;writechar(st[tp--]));
		}
	}
	void cbuf(){
		fwrite(obuf,1,op-obuf,stdout),op=obuf;
	}
};
using io::gi;
using io::writechar;
using io::print;

const int N=1000005,M=8000005,inf=0x7FFFFFFF;
int h[N],nxt[M],to[M],flow[M],tmp=1,n,m,S,T,q[N],l,r,d[N],pp;

void addedge(int u,int v,int f){
	to[++tmp]=v, nxt[tmp]=h[u], h[u]=tmp, flow[tmp]=f;
	to[++tmp]=u, nxt[tmp]=h[v], h[v]=tmp, flow[tmp]=0;
}

struct e{
	int*flow, *revflow, v;
	e(){};
	e(int _v, int*fl, int*rfl){
		flow = fl, revflow = rfl, v = _v;
	}
} edg[M>>1];
int from[M>>1], ed[M>>1], total;

bool bfs(){
	int i,u,v; total = 0;
	for(d[q[l=r=1]=S] = pp;l<=r;l++){
		u=q[l]; from[u]=total+1; pp++;
		for(i=h[u]; i; i=nxt[i]){
			v=to[i];
			if(!flow[i])continue;
			if(d[v]<pp) d[v]=d[u]+1, q[++r]=to[i];
			if(d[v]==d[u]+1) edg[++total] = e(v, flow+i, flow+(i^1));
		}
		ed[u]=total;
	}
	return d[T]>=pp;
}

int dfs(int x,int mf){
	if(x==T)return mf;
	register int res=0,p,i,v,*a,*b;
	for(i=from[x]; i<=ed[x]; i++){
		v=edg[i].v; a=edg[i].flow;
		if (!*a) {from[x]=i+1; continue;}
		p=dfs(v,min(mf,*a)); b=edg[i].revflow;
		*a-=p, *b+=p, res+=p, mf-=p;
		if(!mf) break;
	}
	if(!res) d[x]=-1; 
	return res;
}

int main(){
	gi(n),gi(m),gi(S),gi(T);
	int u,v,c,i;
	for(i=1;i<=m;i++){
		gi(u),gi(v),gi(c);
		if(u==v||!c) continue;
		addedge(u,v,c);
	}
	ll ans=0;
	while(bfs())ans+=dfs(S,inf);
	print(ans);
	io::cbuf();
	return 0;
}

看起来只有改连边方式才能拯救我可怜的代码了……

#include"bits/stdc++.h"

using namespace std;
typedef long long ll;

namespace io{
	const int L=(1<<20)+1;
	char _buf[L],*S,*T,c;
	#define gc (S==T ? T=(S=_buf)+fread(_buf,1,L,stdin), *S++ : *S++)
	void gi(int&x){
		for(c=gc;c<'0'||c>'9';c=gc); x=c&15;
		for(c=gc;c>='0'&&c<='9';c=gc) x=x*10+(c&15);
	}
	char obuf[L],*op=obuf,*end=obuf+(L-1);
	void writechar(char x){
		*op++=x;
		if(op==end)fwrite(obuf,1,L-1,stdout),op=obuf;
	}
	int tp;char st[25];
	template<class T>
	void print(T a){
		if(!a)writechar('0');else{
			for(tp=0;a;st[tp++]=a%10+'0',a/=10);
			for(tp--;~tp;writechar(st[tp--]));
		}
	}
	void cbuf(){
		fwrite(obuf,1,op-obuf,stdout),op=obuf;
	}
};
using io::gi;
using io::writechar;
using io::print;

const int N=1000005,M=8000005,inf=0x7FFFFFFF;

int h[N],nxt[M],to[M],flow[M],tmp=1,n,m,S,T,q[N],l,r,d[N],pp=1;

void addedge(int u,int v,int f){
	to[++tmp]=v, nxt[tmp]=h[u], h[u]=tmp, flow[tmp]=f;
	to[++tmp]=u, nxt[tmp]=h[v], h[v]=tmp, flow[tmp]=0;
}

int from[N], ed[N], A[M>>1], V[M>>1], total;

bool bfs(){
	int i,j=pp,u,v; total = 0;
	for(d[q[l=r=1]=S] = pp;l<=r;l++){
		u=q[l]; from[u]=total+1; pp++;
		for(i=h[u]; i; i=nxt[i]){
			v=to[i];
			if(!flow[i])continue;
			if(d[v]<j) d[v]=d[u]+1, q[++r]=v;
			if(d[v]==d[u]+1) A[++total]=i, V[total]=v;
		}
		ed[u]=total;
	}
	return d[T]>=j;
}

int dfs(int x,int mf){
	if(x==T)return mf;
	register int p,i,v,a;
	for(i=from[x]; i<=ed[x]; i++){
		v=V[i], a=A[i];
		if (!flow[a]) {from[x]=i+1; continue;}
		p=dfs(v, min(mf,flow[a]));
		if (p) {
			flow[a]-=p, flow[a^1]+=p;
			return p;
		} else from[x] = i+1;
		if(!mf) break;
	}
	d[x] = -1;
	return 0;
}

int main(){
	gi(n),gi(m),gi(S),gi(T);
	int u,v,c,i;
	for(i=1;i<=m;i++){
		gi(u),gi(v),gi(c);
		if(u==v||!c) continue;
		addedge(u,v,c);
	}
	ll ans=0; int flow;
	while(bfs()) while(flow=dfs(S,inf)) ans+=flow;
	print(ans);
	io::cbuf();
	return 0;
}

改了方式之后顺利跑上oj第一页

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值