hdu3416--Java-网络流+djk最短路径

题目含义: 一个单向图中(可能有重边), 让你求起点到终点的最短路径有几条?规定每个边只能走一次。

1.利用djk求最短路径
2.根据最小路径dis[]的值,保留,仅在最短路径上的,所有边。得到新图
3.求新图的起点到终点的网络流。

需要想的是:怎样从一个图的所有边中选择出那些在最短路径中的边呢?
方法: 我们从第一步可以到到dis数组,只要这个边(u–v)满足:
dis[u]+ (u,v两点距离) = dis[v]就行了
代码如下

	package coding;
	
	import java.io.BufferedInputStream;
	import java.util.Arrays;
	import java.util.LinkedList;
	import java.util.PriorityQueue;
	import java.util.Queue;
	import java.util.Scanner;
	
	public class hdu3416_2 {
		static int[] dis,vis,L,head,head2;
		static int[][]map;
		static int con,con2,uu,s,e,inf=0x3f3f3f3f,n,m;
		static Queue<Integer>q = new LinkedList<Integer>();
		
		static class e{
			int v,w,next,u;
		}static e[] es;static e[]es2;
		
		static void  add(int u,int v,int w) {
			es[con].u=u;es[con].v=v;es[con].w=w; es[con].next=head[u];head[u]=con++;
		}
		static void  add2(int u,int v,int w) {
			es2[con2].u=u;es2[con2].v=v;es2[con2].w=w; es2[con2].next=head2[u];head2[u]=con2++;
		}
		
		static class qnode implements Comparable<qnode>{
			int no,dis;
			public qnode(int no,int dis) {
				this.no= no;
				this.dis= dis;
			}
			@Override
			public int compareTo(qnode o) {
				return this.dis-o.dis;
			}
		}
		
		static void djk(int a,int b) {
			dis=new int[5000];
			vis=new int[5000];
			PriorityQueue<qnode>pq= new PriorityQueue<qnode>();
			Arrays.fill(dis, inf);
			Arrays.fill(vis,0);
			dis[a]=0;
			pq.add(new qnode(a,0));
			int u,v,w;qnode temp;
			while(!pq.isEmpty()) {
				temp=pq.poll();
				u=temp.no;
				if(vis[u]==1) continue;
				vis[u]=1;
				for(int i=head[u];i!=-1;i=es[i].next) {
					v=es[i].v;
					if(dis[v]>dis[u]+es[i].w) {
						dis[v]=dis[u]+es[i].w;
						pq.add(new qnode(v,dis[v]));
					}
				}
			}
		}
		
		
		static boolean bfs() { 
			Arrays.fill(L, -1);
			q.clear();
			L[s]=0;	
			q.add(s);
			while(!q.isEmpty()) {
				int top =q.poll();
				for(int i=head2[top];i!=-1;i=es2[i].next) {
					int v = es2[i].v;
					if(es2[i].w>0 && L[v]==-1) {
						L[v]=L[top]+1;
						q.add(v);
					}
				}
			}
			return L[e] != -1;
		}
	
		static int dfs(int u,int f) {
			//System.out.println(1231);
			if(u==e || f==0) {
				return f;
			}
			int temp=0,a;
			for(int i=head2[u];i!=-1;i=es2[i].next) {
				int v=es2[i].v;
				if( es2[i].w>0&&(L[v]==L[u]+1)) {
					a= dfs(v,Math.min(es2[i].w, f-temp));
					if(a>0) {
						es2[i].w-=a;
						es2[i^1].w+=a;
						temp+=a;
						if(temp==f) break;
					}
				}
			}
			if(temp==0) L[u]=-1;
			return temp;
		}
		
		
		public static void main(String[] args) {
			Scanner sc=  new Scanner(new BufferedInputStream(System.in));
			int test= sc.nextInt();
			head = new int[5000];
			head2 = new int[5000];
			L=new int [5000];
			es= new e[200010];
			es2= new e[200010];
			
			for( uu=1;uu<=test;uu++) {
				 n=sc.nextInt(); m=sc.nextInt();
				 con = 0;Arrays.fill(head, -1);
				 if(uu==1 ) {
					 for(int i=0;i<es.length;i++) {
						 es[i]=new e();
						 es2[i]=new e();
					 }
				 }
				for(int i=0;i<m;i++) {
					int a=sc.nextInt();int b=sc.nextInt();int c = sc.nextInt();
					add(a,b,c);
				}
				s=sc.nextInt();
				e=sc.nextInt();
				djk(s,e);
				
				con2 = 0;Arrays.fill(head2, -1);
				//这里开始挑选边,构建新图
				for(int i=0;i<m;i++) {
					if(dis[es[i].u]+es[i].w==dis[es[i].v]) {
						add2(es[i].u,es[i].v,1);
						add2(es[i].v,es[i].u,0);
					}
				}
				
				int ans=0;
				while(bfs()) {
					ans+=dfs(s,inf);
				}
				 System.out.println(ans);
			}
		}
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值