HDU 3416 Marriage Match IV 【最短路】(记录路径)+【最大流】
<题目链接>
题目大意:
给你一张图,问你其中没有边重合的最短路径有多少条。
解题分析:
建图的时候记得存一下链式后向边,方便寻找最短路径,然后用Dijkstra或者SPFA跑一遍最短路,从终点开始DFS,找出最短路径上所有的边,然后将其加入网络,所有边的容量置为1,以起点为源点,终点为汇点,跑一遍最大流,求出的结果即为最短路的数量。
Dijkstra+Dinic版:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
;
;
const int INF = 0x3f3f3f3f;
int n, m, st, ed, cnt, cnt1;
int head[N], head1[N], dep[N], tail[N];
bool vis[N];
struct Edge{
int u, v, w, next, next1;
}edge[M<<], edge1[M<<];
struct Node{
int index,dist;
bool operator < (const Node &tmp )const{
return dist>tmp.dist;
}
}node[M<<];
void init(){
cnt = ,cnt1 = ;
memset(head, -, sizeof head);
memset(head1, -, sizeof head1);
memset(tail, -, sizeof tail);
}
void addedge(int u, int v, int w){ //建图,跑最短路
edge[cnt].u = u; edge[cnt].v = v;
edge[cnt].w = w; edge[cnt].next = head[u];
head[u] = cnt;
edge[cnt].next1 = tail[v]; //tail[]数组相当于是反向的head[]数组,链式后向边,用来寻找最短路径上的边
tail[v] = cnt++;
}
void addedge1(int u, int v, int w){ //建图,跑最大流
edge1[cnt1].u = u; edge1[cnt1].v = v;
edge1[cnt1].w = w; edge1[cnt1].next = head1[u];
head1[u] = cnt1++; //正向弧
edge1[cnt1].v = u; edge1[cnt1].u = v;
edge1[cnt1].w = ; edge1[cnt1].next = head1[v];
head1[v] = cnt1++; //反向弧
}
int Dij(){
priority_queue<Node>q;
;i<=n;i++)
vis[i] = false,node[i].index=i,node[i].dist=INF;
node[st].dist=;
q.push(node[st]);
while(!q.empty()){
int u=q.top().index;q.pop();
if(vis[u])continue;
vis[u]=true;
for(int i=head[u];~i;i=edge[i].next){
int v = edge[i].v;
if(node[v].dist>node[u].dist+edge[i].w){
node[v].dist = node[u].dist+edge[i].w;
q.push(node[v]);
}
}
}
return node[ed].dist!= INF;
}
void dfs(int v){ //寻找最短路中的所有边,并将其加入网络
; i = edge[i].next1){
int u = edge[i].u; //u为该后向边的起始点
if(node[u].dist+edge[i].w == node[v].dist){ //判断该边是否为最短路中的边
addedge1(u, v, ); //如果是的话,就加入网络中,跑最大流
if(!vis[u]){
vis[u] = ;
dfs(u);
}
}
}
}
/*-- Dinic --*/
bool bfs(){
memset(vis, , sizeof vis);
memset(dep, -, sizeof dep);
queue<int> q;
q.push(st);
vis[st] = ;
dep[st] = ;
while(!q.empty()){
int cur = q.front();q.pop();
; i = edge1[i].next){
int v = edge1[i].v;
){
dep[v] = dep[cur]+;
vis[v] = ;
q.push(v);
}
}
}
; //如果dep[ed]!=-1,说明仍然存在增广路
}
int dfs1(int cur, int flow){
if(cur == ed) return flow;
;
&& flow > res; i = edge1[i].next){
int v = edge1[i].v;
&& dep[v] == dep[cur]+){
int x = min(edge1[i].w, flow-res);
int f = dfs1(v, x);
edge1[i].w-=f;
edge1[i^].w+=f;
res += f;
}
}
;
return res;
}
int dinic(){
,res;
while(bfs()){
while(res = dfs1(st, INF)){
sumflow += res;
}
}
return sumflow;
}
/*-- Dinic --*/
int main(){
int T; scanf("%d", &T);
while(T--){
init();
scanf("%d%d", &n, &m);
; i < m; i++){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
}
scanf("%d%d", &st, &ed);
"); //跑最短路,如果st->ed不可达,则直接输出0
else{
memset(vis,false,sizeof(vis)); //注意,dijkstra要加上这一句,spfa则不用,因为spfa结束后,所有点的vis全部置为false
dfs(ed); //找到最短路中的所有边,并将其加入网络
printf("%d\n",dinic()); //根据最短路所有的边求最大流
}
}
;
}
SPFA+Dinic版:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
;
;
const int INF = 0x3f3f3f3f;
int n, m, st, ed, cnt, cnt1;
int head[N], head1[N], dis[N], dep[N], tail[N];
bool vis[N];
struct Edge{
int u, v, w, next, next1;
}edge[M<<], edge1[M<<];
void init(){
cnt = ,cnt1 = ;
memset(head, -, sizeof head);
memset(head1, -, sizeof head1);
memset(tail, -, sizeof tail);
}
void addEdge1(int u, int v, int w){ //建图,跑最短路
edge[cnt].u = u; edge[cnt].v = v;
edge[cnt].w = w; edge[cnt].next = head[u];
head[u] = cnt;
edge[cnt].next1 = tail[v]; //tail[]数组相当于是反向的head[]数组,链式后向边,用来寻找最短路径上的边
tail[v] = cnt++;
}
void addEdge2(int u, int v, int w){ //建图,跑最大流
edge1[cnt1].u = u; edge1[cnt1].v = v;
edge1[cnt1].w = w; edge1[cnt1].next = head1[u];
head1[u] = cnt1++; //正向弧
edge1[cnt1].v = u; edge1[cnt1].u = v;
edge1[cnt1].w = ; edge1[cnt1].next = head1[v];
head1[v] = cnt1++; //反向弧
}
int spfa(){
queue<int> q;
; i <= n; i++)
vis[i] = ,dis[i] = INF;
vis[st] = ; dis[st] = ;
q.push(st);
while(!q.empty()){
int cur = q.front();
q.pop(); vis[cur] = ;
; i = edge[i].next)
{
int v = edge[i].v;
if(dis[v] > dis[cur]+edge[i].w)
{
dis[v] = dis[cur]+edge[i].w;
if(!vis[v])
{
vis[v] = ;
q.push(v);
}
}
}
}
return dis[ed] != INF;
}
void dfs(int v){ //寻找最短路中的所有边,并将其加入网络
; i = edge[i].next1){
int u = edge[i].u; //u为该后向边的起始点
if(dis[u]+edge[i].w == dis[v]){ //判断该边是否为最短路中的边
addEdge2(u, v, ); //如果是的话,就加入网络中,跑最大流
if(!vis[u]){
vis[u] = ;
dfs(u);
}
}
}
}
/*-- Dinic --*/
bool bfs(){
memset(vis, , sizeof vis);
memset(dep, -, sizeof dep);
queue<int> q;
q.push(st);
vis[st] = ;
dep[st] = ;
while(!q.empty()){
int cur = q.front();q.pop();
; i = edge1[i].next){
int v = edge1[i].v;
){
dep[v] = dep[cur]+;
vis[v] = ;
q.push(v);
}
}
}
; //如果dep[ed]!=-1,说明仍然存在增广路
}
int dfs1(int cur, int flow){
if(cur == ed) return flow;
;
&& flow > res; i = edge1[i].next){
int v = edge1[i].v;
&& dep[v] == dep[cur]+){
int x = min(edge1[i].w, flow-res);
int f = dfs1(v, x);
edge1[i].w-=f;
edge1[i^].w+=f;
res += f;
}
}
;
return res;
}
int dinic(){
,res;
while(bfs()){
while(res = dfs1(st, INF)){
sumflow += res;
}
}
return sumflow;
}
/*-- Dinic --*/
int main(){
int T; scanf("%d", &T);
while(T--){
init();
scanf("%d%d", &n, &m);
; i < m; i++){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addEdge1(u, v, w);
}
scanf("%d%d", &st, &ed);
"); //跑最短路,如果st->ed不可达,则直接输出0
else{
dfs(ed); //找到最短路中的所有边,并将其加入网络
printf("%d\n",dinic()); //根据最短路所有的边求最大流
}
}
;
}
2018-11-23
HDU 3416 Marriage Match IV 【最短路】(记录路径)+【最大流】的更多相关文章
- HDU 3416 Marriage Match IV (最短路建图+最大流)
(点击此处查看原题) 题目分析 题意:给出一个有n个结点,m条单向边的有向图,问从源点s到汇点t的不重合的最短路有多少条,所谓不重复,意思是任意两条最短路径都不共用一条边,而且任意两点之间的边只会用一 ...
- 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 (最短路径,网络流,最大流)
HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...
- 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(ISAP+最短路)题解
题意:从A走到B,有最短路,问这样不重复的最短路有几条 思路:先来讲选有效边,我们从start和end各跑一次最短路,得到dis1和dis2数组,如果dis1[u] + dis2[v] + cost[ ...
- 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 【 最短路 最大流 】
求边不可重复的最短路条数 先从起点到终点用一次dijkstra,再从终点到起点用一次dijkstra,来判断一条边是否在最短路上 如果在,就将这条边的两个端点连起来,容量为1 再跑一下dinic(), ...
- HDU 3416 Marriage Match IV dij+dinic
题意:给你n个点,m条边的图(有向图,记住一定是有向图),给定起点和终点,问你从起点到终点有几条不同的最短路 分析:不同的最短路,即一条边也不能相同,然后刚开始我的想法是找到一条删一条,然后光荣TLE ...
- HDU 3416 Marriage Match IV
最短路+最大流 #include<cstdio> #include<cstring> #include<string> #include<cmath> ...
随机推荐
- js数组的实例方法sort() 排序方法的运用,不再只是.sort()
1, sort() 不传回调函数的话,默认按照字母顺序(字符编码)的顺序进行排序. 2, sort() 通过传回调函数来控制从小到大的排序还是从大到小的排序: var arr = [1,23,5,6, ...
- bat如何提取文本指定行的内容
背景:使用CTS框架运行完测试后,会在logs中生成devices_log和host_log,在results中生成相应的结果(报告).根据报告信息我们可以得知失败的用例,但是却不能知道为什么用例会失 ...
- Linux 用户(user)和用户组(group)管理概述
一.理解Linux的单用户多任务,多用户多任务概念: Linux 是一个多用户.多任务的操作系统:我们应该了解单用户多任务和多用户多任务的概念: 1.Linux 的单用户多任务:单用户多任务:比如我们 ...
- Java 8 中的 Lambda 表达式
Lambda 表达式是 Java 8 最受欢迎的功能.人们将函数式编程的概念引入了 Java 这门完全面向对象的命令式编程语言. 关于函数式编程是如何运作的,这个话题超出了本文的范围,不过我们会提炼出 ...
- 【ssh】端口转发
来源:https://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/ 非常非常好用,可以通过跳板解决两台服务器无法连接的问题 第一部分 概述 ...
- PDF如何添加水印,PDF添加水印工具的使用方法
PDF文件在编辑修改的时候是需要借助工具才可以编辑,PDF文件不像普通的文件可以直接打开编辑,PDF编辑工具是PDF文件进行编辑的重要工具,就以添加水印为例,能够在PDF中添加水印的工具有哪些呢?要怎 ...
- OAuth2 token
1.资源服务器 package com.ruhuanxingyun.config; import com.fasterxml.jackson.databind.ObjectMapper; import ...
- 通过iostat来查看linux硬盘IO性能|实例分析
iostat查看linux硬盘IO性能 rrqm/s: 每秒进行 merge 的读操作数目.即 delta(rmerge)/s wrqm/s: 每秒进行 merge 的写操作数目.即 delta(wm ...
- Java int类型与String类型互转
String类型转换为int类型 参考:https://blog.csdn.net/qq_35995940/article/details/78433404?locationNum=5&fps ...
- 数据结构C++实现代码-顺序表
参考:https://blog.csdn.net/ebowtang/article/details/43094041 //seqList.h// //包含顺序表中的声明// #include<i ...