• 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);
    	}
    }
    
  • 相关阅读:
    [紫书] 八数码问题(BFS)
    [紫书] 移动盒子(Boxes in a Line)
    [洛谷] P1803 凌乱的yyy / 线段覆盖 (贪心)
    [紫书] 破损的键盘(Broken Keyboard)
    bzoj3891
    poj3233
    bzoj1941
    Vijos2034
    poj2985
    Vijos1100
  • 原文地址:https://www.cnblogs.com/fxq1304/p/13746387.html
Copyright © 2020-2023  润新知