HDU 3416 Marriage Match IV (最短路径,网络流,最大流)

Description

Do not sincere non-interference。

Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once.

So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?

Input

The first line is an integer T indicating the case number.(1<=T<=65)

For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.

Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.

At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.

There may be some blank line between each case.

Output

Output a line with a integer, means the chances starvae can get at most.

Sample Input

3

7 8

1 2 1

1 3 1

2 4 1

3 4 1

4 5 1

4 6 1

5 7 1

6 7 1

1 7

6 7

1 2 1

2 3 1

1 3 3

3 4 1

3 5 1

4 6 1

5 6 1

1 6

2 2

1 2 1

1 2 2

1 2

Sample Output

2

1

1

Http

HDU:https://vjudge.net/problem/HDU-3416

Source

最短路径,网络流,最大流

题目大意

在给定的有向图中指定一个起点一个终点,求有几条边不重复的最短路径

解决思路

这道题刚开始看以为是一道费用流问题,但发现题目中要求走的只能是最短路径,所以可以知道最短路径是用来限制只能走一些边的,那么我们只要在求解最大流时(这里用Dinic实现)在bfs构造分层图时加入限制只能走最短路经过的边。

至于如何求出那些边是最短路边呢?我们可以正着跑一边最短路径(从起点到终点),再反着跑一边最短路径(从终点到起点,注意因为是有向边,所以边要反向)。注意,在网络流建图时其实是加入了反向边的,那么这里我们可以借助最小费用流的思想,把反边的费用置为-cost,那么我们在求解最短路径时就可以知道哪些是原图中的边而哪些是反边了。

如果我们将正着跑的最短路径放入Dist[1]中,反着跑的最短路径放入Dist[2]中,那么对于一条边u->v边权为w,若Dist[1][u]+w+Dist[2][v]==Dist[1][终点],则这条边是最短路边

然后我们把边的容量置为1(因为要满足没有重边),再对于这些限制条件跑最大流即可

另:这里使用Dinic实现最大流,可以参考这篇文章

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std; const int maxN=1100;
const int maxM=103001*10;
const int inf=2147483647; class Edge
{
public:
int u,v,cost,flow;//注意,这里虽然看起来和费用流的边构造是一样的,其实只是为了方便将最短路径的信息放进来了,实则无联系
}; int n,m;
int st,ed;//起点和终点
int cnt;
int Head[maxN];
int Next[maxM];
Edge E[maxM];
int Dist[3][maxN];//Dist[1]记录正着的最短路,Dist[2]记录反着的最短路
int Q[maxM];
bool inqueue[maxN];
int cur[maxN];//当前弧优化
int depth[maxN]; void Add_Edge(int u,int v,int cost,int flow);
void spfa1();//正着最短路
void spfa2();//反着最短路
bool bfs();
int dfs(int u,int flow); int main()
{
int T;
scanf("%d",&T);
while (T--)
{
cnt=-1;
memset(Head,-1,sizeof(Head));//多组数据先置空
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
Add_Edge(u,v,w,1);//加边,注意因为一条边只能走一次,所以容量置为1
}
scanf("%d%d",&st,&ed);
spfa1();//正反分别最短路
spfa2();
/*
for (int i=1;i<=n;i++)
cout<<Dist[1][i]<<" ";
cout<<endl;
for (int i=1;i<=n;i++)
cout<<Dist[2][i]<<' ';
cout<<endl;
//*/
int Ans=0;//求解最大流
while (bfs())
{
for (int i=1;i<=n;i++)
cur[i]=Head[i];
while (dfs(st,inf))
Ans++;//注意这里每找到一条是+1,说明找到
}
printf("%d\n",Ans);
}
return 0;
} void Add_Edge(int u,int v,int cost,int flow)
{
cnt++;
Next[cnt]=Head[u];
Head[u]=cnt;
E[cnt].u=u;
E[cnt].v=v;
E[cnt].cost=cost;
E[cnt].flow=flow; cnt++;//反边,注意与正边的区别
Next[cnt]=Head[v];
Head[v]=cnt;
E[cnt].u=v;
E[cnt].v=u;
E[cnt].cost=-cost;
E[cnt].flow=0;
return;
} void spfa1()//正着最短路
{
memset(Dist[1],127,sizeof(Dist[1]));
memset(inqueue,0,sizeof(inqueue));
int h=1,t=0;
Q[1]=st;//起点是st
Dist[1][st]=0;
inqueue[st]=1;
do
{
t++;
int u=Q[t];
for (int i=Head[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((E[i].flow>0)&&(E[i].cost+Dist[1][u]<Dist[1][v]))//注意这里利用了初始时正边的流量>0的性质来判断是否是正边
{
Dist[1][v]=Dist[1][u]+E[i].cost;
if (inqueue[v]==0)
{
h++;
Q[h]=v;
inqueue[v]=1;
}
}
}
inqueue[u]=0;
}
while (t!=h);
return;
} void spfa2()//反着最短路
{
memset(Dist[2],127,sizeof(Dist[2]));
memset(inqueue,0,sizeof(inqueue));
int h=1,t=0;
Q[1]=ed;//起点是ed
inqueue[ed]=1;
Dist[2][ed]=0;
do
{
t++;
int u=Q[t];
for (int i=Head[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((E[i].cost<0)&&(Dist[2][u]-E[i].cost<Dist[2][v]))//因为反边的边权是负数,所以可以用来标记是否是反边,同时注意松弛时是加上其相反数
{
Dist[2][v]=Dist[2][u]-E[i].cost;
if(inqueue[v]==0)
{
h++;
Q[h]=v;
inqueue[v]=1;
}
}
}
inqueue[u]=0;
}
while (t!=h);
return;
} bool bfs()//构造分层图
{
memset(depth,-1,sizeof(depth));
int h=1,t=0;
Q[1]=st;
depth[st]=1;
do
{
t++;
int u=Q[t];
for (int i=Head[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((E[i].flow>0)&&(depth[v]==-1)&&(Dist[1][u]+E[i].cost+Dist[2][v]==Dist[1][ed]))//注意这里与普通的Dinic多加了一个条件,即这条边必须是最短路边
{
depth[v]=depth[u]+1;
h++;
Q[h]=v;
}
}
}
while (t!=h);
if (depth[ed]==-1)
return 0;
return 1;
} int dfs(int u,int flow)
{
if (u==ed)
return flow;
for (int &i=cur[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((depth[v]==depth[u]+1)&&(E[i].flow>0)&&(Dist[1][u]+E[i].cost+Dist[2][v]==Dist[1][ed]))//这里的判断也多了一个条件,同样是判断是否是最短路边
{
int di=dfs(v,min(flow,E[i].flow));
if (di>0)
{
E[i].flow-=di;
E[i^1].flow+=di;
return di;
}
}
}
return 0;
}

HDU 3416 Marriage Match IV (最短路径,网络流,最大流)的更多相关文章

  1. HDU 3416 Marriage Match IV (Dijkstra+最大流)

    题意:N个点M条边的有向图,给定起点S和终点T,求每条边都不重复的S-->T的最短路有多少条. 分析:首先第一步需要找出所有可能最短路上的边.怎么高效地求出呢?可以这样:先对起点S,跑出最短路: ...

  2. hdu 3416 Marriage Match IV (最短路+最大流)

    hdu 3416 Marriage Match IV Description Do not sincere non-interference. Like that show, now starvae ...

  3. HDU 3416 Marriage Match IV (求最短路的条数,最大流)

    Marriage Match IV 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/Q Description Do not si ...

  4. HDU 3416 Marriage Match IV(最短路,网络流)

    题面 Do not sincere non-interference. Like that show, now starvae also take part in a show, but it tak ...

  5. HDU 3416 Marriage Match IV (最短路径&&最大流)

    /*题意: 有 n 个城市,知道了起点和终点,有 m 条有向边,问从起点到终点的最短路一共有多少条.这是一个有向图,建边的时候要注意!!解题思路:这题的关键就是找到哪些边可以构成最短路,其实之前做最短 ...

  6. HDU 3416 Marriage Match IV dij+dinic

    题意:给你n个点,m条边的图(有向图,记住一定是有向图),给定起点和终点,问你从起点到终点有几条不同的最短路 分析:不同的最短路,即一条边也不能相同,然后刚开始我的想法是找到一条删一条,然后光荣TLE ...

  7. HDU 3416 Marriage Match IV (最短路建图+最大流)

    (点击此处查看原题) 题目分析 题意:给出一个有n个结点,m条单向边的有向图,问从源点s到汇点t的不重合的最短路有多少条,所谓不重复,意思是任意两条最短路径都不共用一条边,而且任意两点之间的边只会用一 ...

  8. HDU 3416 Marriage Match IV 【最短路】(记录路径)+【最大流】

    <题目链接> 题目大意: 给你一张图,问你其中没有边重合的最短路径有多少条. 解题分析: 建图的时候记得存一下链式后向边,方便寻找最短路径,然后用Dijkstra或者SPFA跑一遍最短路, ...

  9. HDU 3416 Marriage Match IV(ISAP+最短路)题解

    题意:从A走到B,有最短路,问这样不重复的最短路有几条 思路:先来讲选有效边,我们从start和end各跑一次最短路,得到dis1和dis2数组,如果dis1[u] + dis2[v] + cost[ ...

随机推荐

  1. .net core实践系列之短信服务-Sikiro.SMS.Bus服务的实现

    前言 前两篇<.net core实践系列之短信服务-Sikiro.SMS.Api服务的实现>.<.net core实践系列之短信服务-Api的SDK的实现与测试>分别讲解了AP ...

  2. Ext JS 4 的类系统

    前言 我们知道,JavaScript中没有真正的类,它是一种面向原型的语言 .这种语言一个强大的特性就是灵活,实现一个功能可以有很多不同的方式,用不同的编码风格和技巧.但随之也带来了代码的不可预测和难 ...

  3. [T-ARA N4/二段横踢][Can We Love]

    歌词来源:http://music.163.com/#/song?id=26310867 Can We Love Can We Love [Can We Love Can We Love] Can W ...

  4. ZooKeeper 典型的应用场景——及编程实现

    如何使用 Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但是 Zookeeper 并不是用来专门存储 ...

  5. Python-习题-11

    1,内容回顾列表:增 append insert extend 删 remove pop clear del 改 li[索引] = '被修改的内容' li[切片]:'被修改的内容' 查 for循环 r ...

  6. pl/sql破解方法

    转载源:http://blog.csdn.net/oscar999/article/details/2123803 打开注册表在run下输入regedit删除1.HKEY_CURRENT_USER/S ...

  7. 使用Java+Kotlin双语言的LeetCode刷题之路(二)

    BasedLeetCode LeetCode learning records based on Java,Kotlin,Python...Github 地址 序号对应 LeetCode 中题目序号 ...

  8. Beta阶段敏捷冲刺五

    一.举行站立式会议 1.当天站立式会议照片一张 2.团队成员报告 林楚虹 (1) 昨天已完成的工作:排行榜功能.完善从数据库读取单词放入缓存功能(即完善select.js) (2) 今天计划完成的工作 ...

  9. [读书笔记]Linux命令行与shell编程读书笔记02 环境变量以及其他

    1. Linux的环境变量. 全局环境变量的查看 printenv 一个结果示例 XDG_SESSION_ID=354TERM=xtermSHELL=/bin/bashSSH_CLIENT=10.24 ...

  10. session存入redis

    Session信息入Redis Session简介 session,中文经常翻译为会话,其本来的含义是 指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一 ...