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