hdu3416 最短路+最大流

hdu3416 Marriage Match IV
传送门

题意

给出一个\(n(2\leq n\leq 1000)\)个点,\(m(0\leq m\leq 100000)\)条边的有向图,以及起点\(A\)和终点\(B\),计算从\(A\)\(B\)的不相交的最短路的条数。

题解

首先通过堆优化\(Dijkstra\)计算\(A\)到所有点的最短路的长度\(dis\_A[maxn]\),以及\(B\)到所有点的最短路的长度\(dis\_B[maxn]\)
之后枚举所有的边,如果对于一条边,有\(dis\_A[u]+dis\_B[v]+w==dis\_A[B]\),说明这条边有可能是某一条从\(A\)\(B\)的最短路上的边,将这条边的流量设为\(1\)
最后计算从\(A\)\(B\)的最大流

#include<bits/stdc++.h>
#define LL long long
#define PII pair<int,int>
#define PLI pair<LL,int>
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
using namespace std;

const int maxn=1010,maxm=100010;
const LL inf=0x3f3f3f3f3f3f3f3f;
int T,n,m,A,B;
int head1[maxn],to1[maxm],nxt1[maxm],cnt1;
int head2[maxn],to2[maxm],nxt2[maxm],cnt2;
int head3[maxn],to3[2*maxm],nxt3[2*maxm],cnt3,cur[maxn],depth[maxn];
int book[maxn];
LL w1[maxm];
LL w2[maxm];
LL w3[2*maxm];
LL dis_A[maxn],dis_B[maxn];

void init(){
	memset(head1,-1,sizeof(head1));
	cnt1=0;
	memset(head2,-1,sizeof(head2));
	cnt2=0;
	memset(head3,-1,sizeof(head3));
	cnt3=0;
}

void add1(int u,int v,LL c){
	to1[cnt1]=v;
	w1[cnt1]=c;
	nxt1[cnt1]=head1[u];
	head1[u]=cnt1++;
}

void add2(int u,int v,LL c){
	to2[cnt2]=v;
	w2[cnt2]=c;
	nxt2[cnt2]=head2[u];
	head2[u]=cnt2++;
}

void add3(int u,int v,LL c){
	to3[cnt3]=v;
	w3[cnt3]=c;
	nxt3[cnt3]=head3[u];
	head3[u]=cnt3++;
}

void Dijkstra1(){
	for(int i=1;i<=n;i++){
		dis_A[i]=inf;
		book[i]=0;
	}
	dis_A[A]=0;
	book[A]=1;
	for(int i=head1[A];~i;i=nxt1[i]){
		int v=to1[i];
		LL c=w1[i];
		dis_A[v]=min(dis_A[v],dis_A[A]+c);
	}
	for(int i=1;i<n;i++){
		int id;
		LL mini=inf;
		for(int j=1;j<=n;j++){
			if(!book[j] && mini>dis_A[j]){
				mini=dis_A[j];
				id=j;
			}
		}
		book[id]=1;
		for(int j=head1[id];~j;j=nxt1[j]){
			int v=to1[j];
			LL c=w1[j];
			dis_A[v]=min(dis_A[v],dis_A[id]+c);
		}
	}
}

void Dijkstra2(){
	for(int i=1;i<=n;i++){
		dis_B[i]=inf;
		book[i]=0;
	}
	dis_B[B]=0;
	book[B]=1;
	for(int i=head2[B];~i;i=nxt2[i]){
		int v=to2[i];
		LL c=w2[i];
		dis_B[v]=min(dis_B[v],dis_B[B]+c);
	}
	for(int i=1;i<n;i++){
		int id;
		LL mini=inf;
		for(int j=1;j<=n;j++){
			if(!book[j] && mini>dis_B[j]){
				mini=dis_B[j];
				id=j;
			}
		}
		book[id]=1;
		for(int j=head2[id];~j;j=nxt2[j]){
			int v=to2[j];
			LL c=w2[j];
			dis_B[v]=min(dis_B[v],dis_B[id]+c);
		}
	}
}

void f(int u){
	book[u]=1;
	for(int i=head1[u];~i;i=nxt1[i]){
		int v=to1[i];
		LL c=w1[i];
		if(!book[v]) f(v);
		if(dis_A[u]+dis_B[v]+c==dis_A[B]){
			add3(u,v,1);
			add3(v,u,0);
		}
	}
}

LL dfs(int u,LL flow){
	if(u==B) return flow;
	for(int& i=cur[u];~i;i=nxt3[i]){
		int v=to3[i];
		if(depth[v]==depth[u]+1 && w3[i]!=0){
			LL di=dfs(v,min(flow,w3[i]));
			if(di>0){
				w3[i]-=di;
				w3[i^1]+=di;
				return di;
			}
		}
	}
	return 0;
}

bool bfs(){
	queue<int> q;
	for(int i=1;i<=n;i++) depth[i]=0;
	depth[A]=1;
	q.push(A);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=head3[u];~i;i=nxt3[i]){
			int v=to3[i];
			if(depth[v]==0 && w3[i]>0){
				depth[v]=depth[u]+1;
				q.push(v);
			}
		}
	}
	if(depth[B]>0) return 1;
	return 0;
}

LL dinic(){
	LL ans=0;
	while(bfs()){
		for(int i=1;i<=n;i++){
			cur[i]=head3[i];
		}
		while(LL d=dfs(A,inf)){
			ans+=d;
		}
	}
	return ans;
}

int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&m);
		init();
		for(int i=0;i<m;i++){
			int u,v;
			LL c;
			scanf("%d %d %lld",&u,&v,&c);
			add1(u,v,c);
			add2(v,u,c);
		}
		scanf("%d %d",&A,&B);
		Dijkstra1();
		Dijkstra2();
		for(int i=1;i<=n;i++) book[i]=0;
		f(A);
		LL ans=dinic();
		printf("%lld\n",ans);
	}
}
原文地址:https://www.cnblogs.com/fxq1304/p/13746387.html