【[CQOI2015]网络吞吐量】最大流板题

不开longlong 毁一生。

luogu传送门:https://www.luogu.org/problemnew/show/P3171

首先先跑一个最短路上的所有最短路径,然后加入图中跑一次最大流就可以,还是比较裸的一道题。if(dis[x]+len[y]==dis[y])则这条路在最短路上。然后看每个点的吞吐量限制,我们将每个路由器拆成两个点来考虑,从一个点到这个点的镜像结点的容量为其限制就可以了,其他边直接连图,容量为inf。

然而这道题有坑点。。首先起始点没有吞吐量限制!要特判!还有就是要开longlong ,inf也要设大一些。int,一分都没有,,,

大概就是这样吧。。以下是sap代码

#include<bits/stdc++.h>
using namespace std;
long long n,m;
long long owo,dis[300005],en[300005],nt[300005],la[300005],len[300005];
long long v[1005][1005];
long long fr[300005],to[300005],cd[300005];
long long cnt[1005]; 
void addedge(long long a,long long b,long long c)
{
	en[++owo]=b; nt[owo]=la[a]; la[a]=owo; len[owo]=c;
}
long long dijdis[1005];
struct node
{
	long long di,tt;
}tmp;
priority_queue<node>q;
bool operator<(const node &aa,const node &bb)
{ return aa.di>bb.di; }  
void dijkstra(long long x)
{
	long long ddd;
	for(long long i=1;i<=n;i++) dijdis[i]=0x3f3f3f3f;
	dijdis[1]=0; q.push((node){0,1});
	while(q.size())
	{
		x=q.top().tt; ddd=q.top().di; q.pop();
		if(ddd!=dijdis[x]) continue;
		for(long long it=la[x];it;it=nt[it])
		{
			if(dijdis[en[it]]>ddd+len[it])
			{
				dijdis[en[it]]=ddd+len[it];
				q.push((node){ddd+len[it],en[it]});
			}
		}
	}
}
long long sap(long long x,long long flow)
{
	if(x==2*n) return flow;
	long long delta=0,tmp;
	for(long long i=1;i<=2*n;i++)
	{
		if(v[x][i]&&dis[x]==dis[i]+1)
		{
			tmp=sap(i,min(flow-delta,v[x][i]));
			delta+=tmp;
			v[x][i]-=tmp;
			v[i][x]+=tmp;
			if(delta==flow||dis[1]>=2*n) return delta;
		}
	}
	if(dis[1]>=2*n) return delta;
	cnt[dis[x]]--;
	if(!cnt[dis[x]]) dis[1]=2*n;
	dis[x]++;
	cnt[dis[x]]++;
	return delta;
}
int main()
{
	long long a,b,c;
	scanf("%lld%lld",&n,&m);
	for(long long i=1;i<=m;i++)
	{
		scanf("%lld%lld%lld",&a,&b,&c);
		addedge(a,b,c);
		addedge(b,a,c);
		fr[i]=a; to[i]=b; cd[i]=c;
	}
	dijkstra(1);
	long long x,y;
	for(long long i=1;i<=n;i++)
	{
		scanf("%lld",&x);
		if(i!=n&&i!=1)v[i][i+n]=x;
		else v[i][i+n]=1e14;
	}
	for(long long i=1;i<=m;i++)
	{
		if(dijdis[fr[i]]+cd[i]==dijdis[to[i]]) v[fr[i]+n][to[i]]=1e14;
		if(dijdis[to[i]]+cd[i]==dijdis[fr[i]]) v[to[i]+n][fr[i]]=1e14;
	}
	long long ans=0;
	while(dis[1]<2*n)
	{
		ans+=sap(1,1e14);
	}
	printf("%lld",ans);
}

 

posted @ 2018-04-13 16:48  Newuser233  阅读(5)  评论(0)    收藏  举报