BZOJ 3931: [CQOI2015]网络吞吐量【最短路+网络流

80 篇文章 0 订阅
5 篇文章 0 订阅

裸的最短路+乱搞+拆点+网络流

……忘了拆点会点数<<1,于是数组开小了又WA又T了一年【跪地不起我………………


反正点的流量限制就把它拆成入点和出点两个,中间加一条边就好了

找所有最短路直接for边就好……

…………拆点…………注意………………数组…………开大…………………………


裸题T了一年……果然我是要退役了QAQ


#include<bits/stdc++.h>
//#define Flaze_naive
#define MAXN 1515
#define MAXM 100057
#define INF 1000000000000000000ll
using namespace std;	int n,m;
int read_x[MAXM],read_y[MAXM],read_l[MAXM];
int S=0,T;
long long dis[MAXN];
int in_que[MAXN],que[MAXN],head,tail;
long long ans=0;

void addedge(int x,int y,long long liu);

struct t1{
	int to,lth;
	t1(){}
	t1(int to,int lth):to(to),lth(lth){}
};
vector<t1> e[MAXN];

void SPFA(int now){
	memset(dis,0x3f3f3f3f,sizeof dis);
	head=tail=0;
	que[tail++]=now;
	in_que[now]=1;
	dis[now]=0;
	while(head^tail){
		now=que[head++];
		if(head==MAXN)	head=0;
		in_que[now]=0;
		for(int tmp=0;tmp<e[now].size();++tmp){
			int aim=e[now][tmp].to;
			if(dis[aim]>dis[now]+e[now][tmp].lth){
				dis[aim]=dis[now]+e[now][tmp].lth;
				if(!in_que[aim])	que[tail++]=aim,in_que[aim]=1;
				if(tail==MAXN)	tail=0;
			}
		}
	}
}

int c[MAXN];
int iin[MAXN],ott[MAXN];
int cnt_node=0;
void build(int now){
	iin[1]=ott[1]=++cnt_node,iin[n]=ott[n]=++cnt_node;
	for(int i=2;i<n;++i)	
		iin[i]=++cnt_node,ott[i]=++cnt_node,
		addedge(iin[i],ott[i],c[i]);
	T=++cnt_node;
	addedge(S,iin[1],INF),addedge(ott[n],T,INF);	
	
	for(int i=1;i<=m;++i){
		if(dis[read_x[i]]==dis[read_y[i]]+read_l[i])
			addedge(ott[read_y[i]],iin[read_x[i]],INF);
		if(dis[read_x[i]]+read_l[i]==dis[read_y[i]])
			addedge(ott[read_x[i]],iin[read_y[i]],INF);
	}
}
//=======================================================================================
struct edge_for_dinic{
	int to,nxt;
	long long liu;
	int tag;
	edge_for_dinic(){}
	edge_for_dinic(int to,int nxt,long long liu):to(to),nxt(nxt),liu(liu){}
}edge[MAXM<<2];	int cnt_edge=1;
int fst[MAXN<<1],cur[MAXN<<1];

void addedge(int x,int y,long long liu){
	edge[++cnt_edge]=edge_for_dinic(y,fst[x],liu);
	fst[x]=cnt_edge;
	edge[++cnt_edge]=edge_for_dinic(x,fst[y],0);
	fst[y]=cnt_edge;
}

long long dfs(int now,long long low){
	if(now==T)	return low;
	long long rst=low;
	for(int &tmp=cur[now];tmp;tmp=edge[tmp].nxt){
		if(dis[now]+1!=dis[edge[tmp].to]||edge[tmp].liu<=0)	continue;
		int aim=edge[tmp].to;
		long long tt=dfs(aim,min(rst,edge[tmp].liu));
		if(tt){
			edge[tmp].liu-=tt;
			edge[tmp^1].liu+=tt;
			rst-=tt;
			if(!rst)	return low;
		}
	}
	if(low==rst)	dis[now]=-1;
	return low-rst;
}

bool bfs(int now){
	memset(dis,-1,sizeof dis);
	head=tail=0;
	que[tail++]=now;
	dis[now]=0;
	for(int i=S;i<=cnt_node;++i)	cur[i]=fst[i];
	cur[T]=fst[T];
	while(head^tail){
		now=que[head++];
		if(head==MAXN)	head=0;
		for(int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
			int aim=edge[tmp].to;
			if(dis[aim]!=-1||edge[tmp].liu<=0)	continue;
			dis[aim]=dis[now]+1;
			que[tail++]=aim;
			if(tail==MAXN)	tail=0;
		}
	}
	return ~dis[T];
}

void dinic(){
	long long tt;
	while(bfs(S)){
		while(tt=dfs(S,INF))
			ans+=tt;
	}
}

//=======================================================================================


int main(){
#ifdef Flaze_naive
	freopen("1.in","r",stdin);
#endif 	
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i){
		scanf("%d%d%d",&read_x[i],&read_y[i],&read_l[i]);
		if(read_x[i]==read_y[i])	continue;
		e[read_x[i]].push_back(t1(read_y[i],read_l[i]));
		e[read_y[i]].push_back(t1(read_x[i],read_l[i]));
	}
	SPFA(1);
	for(int i=1;i<=n;++i)	scanf("%d",c+i);
	build(n);
	dinic();
	printf("%lld",ans);
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值