HDU 3416 Marriage Match IV (最短路径,网络流,最大流)
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 (最短路径,网络流,最大流)的更多相关文章
- HDU 3416 Marriage Match IV (Dijkstra+最大流)
题意:N个点M条边的有向图,给定起点S和终点T,求每条边都不重复的S-->T的最短路有多少条. 分析:首先第一步需要找出所有可能最短路上的边.怎么高效地求出呢?可以这样:先对起点S,跑出最短路: ...
- hdu 3416 Marriage Match IV (最短路+最大流)
hdu 3416 Marriage Match IV Description Do not sincere non-interference. Like that show, now starvae ...
- HDU 3416 Marriage Match IV (求最短路的条数,最大流)
Marriage Match IV 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/Q Description Do not si ...
- HDU 3416 Marriage Match IV(最短路,网络流)
题面 Do not sincere non-interference. Like that show, now starvae also take part in a show, but it tak ...
- HDU 3416 Marriage Match IV (最短路径&&最大流)
/*题意: 有 n 个城市,知道了起点和终点,有 m 条有向边,问从起点到终点的最短路一共有多少条.这是一个有向图,建边的时候要注意!!解题思路:这题的关键就是找到哪些边可以构成最短路,其实之前做最短 ...
- HDU 3416 Marriage Match IV dij+dinic
题意:给你n个点,m条边的图(有向图,记住一定是有向图),给定起点和终点,问你从起点到终点有几条不同的最短路 分析:不同的最短路,即一条边也不能相同,然后刚开始我的想法是找到一条删一条,然后光荣TLE ...
- HDU 3416 Marriage Match IV (最短路建图+最大流)
(点击此处查看原题) 题目分析 题意:给出一个有n个结点,m条单向边的有向图,问从源点s到汇点t的不重合的最短路有多少条,所谓不重复,意思是任意两条最短路径都不共用一条边,而且任意两点之间的边只会用一 ...
- HDU 3416 Marriage Match IV 【最短路】(记录路径)+【最大流】
<题目链接> 题目大意: 给你一张图,问你其中没有边重合的最短路径有多少条. 解题分析: 建图的时候记得存一下链式后向边,方便寻找最短路径,然后用Dijkstra或者SPFA跑一遍最短路, ...
- HDU 3416 Marriage Match IV(ISAP+最短路)题解
题意:从A走到B,有最短路,问这样不重复的最短路有几条 思路:先来讲选有效边,我们从start和end各跑一次最短路,得到dis1和dis2数组,如果dis1[u] + dis2[v] + cost[ ...
随机推荐
- [React]全自动数据表格组件——BodeGrid
表格是在后台管理系统中用的最频繁的组件之一,相关的功能有数据的新增和编辑.查询.排序.分页.自定义显示以及一些操作按钮.我们逐一深入进行探讨以及介绍我的设计思路: 新增和编辑 想想我们最开始写新增 ...
- js中的栈、堆、队列、内存空间
栈(stack) .堆(heap). 队列(queue)是js的三种数据结构. 栈(stack) 栈的特点是"LIFO,即后进先出(Last in, first out)".数据存 ...
- flask-socketio笔记
Flask-SocketIO使Flask应用程序可以访问客户端和服务器之间的低延迟双向通信. 客户端应用程序可以使用Javascript,C ++,Java和Swift中的任何SocketIO官方客户 ...
- http指南(2)--代理
代理 单个客户端专用的代理称为私有代理,众多客户端共享的代理被称为公共代理 代理与网关的对比:代理连接的是两个或多个使用相同协议的应用程序,而网关连接的则是两个或多个使用不同协议的端点.网关扮演的是“ ...
- Android恶意样本数据集汇总
硕士论文的研究方向为Android恶意应用分类,因此花了一点时间去搜集Android恶意样本.其中一部分来自过去论文的公开数据集,一部分来自社区或平台的样本.现做一个汇总,标明了样本或数据集的采集时间 ...
- 【nodejs】让nodejs像后端mvc框架(asp.net mvc )一样处理请求--自动路由篇(1/8)【route】
文章目录 前情概要 在使用express框架开发的时候,每加一个请求,都在增加一条route请求规则,类似于下面的代码,很烦有木有! app.use('/myroute path', (req, re ...
- c#代码分析
代码分析是在一个IT行业计算机程序员必须要具有的基本专业技能,在了解一定的专业基础之上去看懂别人编写的代码,分析别人代码实现的功能,以及基本的维护和扩展测试.不同的人有不同的代码风格,要使自己的能要别 ...
- 《linux内核设计与实现》读书笔记——第三章
- 关于<T> T[] toArray(T[] a) 方法
http://mopishv0.blog.163.com/blog/static/5445593220101016102129741/ private List<String> uploa ...
- 记Git报错-refusing to merge unrelated histories
记Git报错-refusing to merge unrelated histories 系统:win7 git版本: 2.16.2.windows.1 问题 1.本地初始化了git仓库,放了一些 ...