HDU 3416:Marriage Match IV(最短路+最大流)
http://acm.hdu.edu.cn/showproblem.php?pid=3416
题意:给出n个点m条边,边信息分别是两个端点和一个费用,再给出一个起点和一个终点,问从起点到终点的完全不相同的最短路径有多少条。(即走过的边不能在走过了)。
思路:因为是在网络流专题里面,所以一开始以为先用SPFA跑一个最小费用出来,然后再用最小费用最大流(然而是最小费用最大流是满足最大流的前提下再考虑最小费用的,很明显是行不通的)。后来想要保证路径不重复,就跑完一次最短路就删除路径(好像也是行不通)。然后只能看下题解了= =。
从起点到终点跑一次SPFA,再从终点到起点跑一次SPFA,这里第一次SPFA跑出来的距离数组是d[0],第二次跑出来的是d[1],如果d[0][u] + w(u, v) + d[1][v] == d[0][T],那么这条w(u,v)边一定是最短路上的边。这里说说我对这个定理的看法:d[0][u]是从起点到u点的最短距离,而d[1][v]是从v到终点的最短距离,那么如果加上这条边刚好等于从起点到终点的最短距离,那么这条边就必定是最短路的边,嗯。好像很明显。然后将这些必定在最短路上的边建起网络,容量是1,跑一遍从起点到终点的最大流,就是最终答案了。这样就符合最大流的思想了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
#define N 1010
#define M 200010
#define INF 0x3f3f3f3f
struct Edge {
int v, cap, nxt;
Edge () {}
Edge (int v, int nxt, int cap) : v(v), nxt(nxt), cap(cap) {}
} edge[M], e[M];
int cur[N], pre[N], gap[N], dis[N], d[][N], vis[N], head[N], h[N], uu[M], vv[M], ww[M], tot, tt, S, T, n, m; void Add(int u, int v, int cap, int tag) {
if(tag == ) { e[tt] = Edge(v, h[u], cap); h[u] = tt++; }
else { edge[tot] = Edge(v, head[u], cap); head[u] = tot++; edge[tot] = Edge(u, head[v], ); head[v] = tot++; }
} void SPFA(int st, int ed, int id) {
for(int i = ; i <= n; i++) d[id][i] = INF;
memset(vis, , sizeof(vis));
queue<int> que; que.push(st);
vis[st] = ; d[id][st] = ;
while(!que.empty()) {
int u = que.front(); que.pop(); vis[u] = ;
for(int i = h[u]; ~i; i = e[i].nxt) {
int v = e[i].v, w = e[i].cap;
if(d[id][v] > d[id][u] + w) {
d[id][v] = d[id][u] + w;
if(vis[v]) continue;
que.push(v); vis[v] = ;
}
}
}
} void BFS() {
memset(dis, INF, sizeof(dis));
memset(gap, , sizeof(gap));
queue<int> que; que.push(T);
dis[T] = ; gap[]++;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(dis[v] != INF) continue;
dis[v] = dis[u] + ;
gap[dis[v]]++;
que.push(v);
}
}
} int ISAP(int n) {
BFS();
memcpy(cur, head, sizeof(cur));
int u = pre[S] = S, ans = , flow, i, index;
while(dis[S] < n) {
if(u == T) {
flow = INF;
for(i = S; i != T; i = edge[cur[i]].v)
if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
for(i = S; i != T; i = edge[cur[i]].v)
edge[cur[i]].cap -= flow, edge[cur[i]^].cap += flow;
u = index; ans += flow;
}
for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap > && dis[edge[i].v] + == dis[u]) break;
if(~i) { cur[u] = i; pre[edge[i].v] = u; u = edge[i].v; }
else {
if(--gap[dis[u]] == ) break;
int md = n + ;
for(i = head[u]; ~i; i = edge[i].nxt)
if(dis[edge[i].v] < md && edge[i].cap > ) md = dis[edge[i].v], cur[u] = i;
gap[dis[u] = md + ]++;
u = pre[u];
}
}
return ans;
} int main() {
int t;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
int edgenum = ;
for(int i = ; i <= m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
//if(u == v) continue;
edgenum++; uu[edgenum] = u; vv[edgenum] = v; ww[edgenum] = w;
}
scanf("%d%d", &S, &T);
memset(h, -, sizeof(h)); tt = ;
for(int i = ; i <= edgenum; i++) Add(uu[i], vv[i], ww[i], );
SPFA(S, T, );
memset(h, -, sizeof(h)); tt = ;
for(int i = ; i <= edgenum; i++) Add(vv[i], uu[i], ww[i], );
SPFA(T, S, );
memset(head, -, sizeof(head)); tot = ;
for(int i = ; i <= edgenum; i++)
if(d[][uu[i]] + d[][vv[i]] + ww[i] == d[][T]) Add(uu[i], vv[i], , ); // 容量设成1.而不是ww
int ans = ISAP(n + );
printf("%d\n", ans);
}
return ;
}
HDU 3416:Marriage Match IV(最短路+最大流)的更多相关文章
- HDU 3416 Marriage Match IV (最短路建图+最大流)
(点击此处查看原题) 题目分析 题意:给出一个有n个结点,m条单向边的有向图,问从源点s到汇点t的不重合的最短路有多少条,所谓不重复,意思是任意两条最短路径都不共用一条边,而且任意两点之间的边只会用一 ...
- HDU 3416 Marriage Match IV (Dijkstra+最大流)
题意:N个点M条边的有向图,给定起点S和终点T,求每条边都不重复的S-->T的最短路有多少条. 分析:首先第一步需要找出所有可能最短路上的边.怎么高效地求出呢?可以这样:先对起点S,跑出最短路: ...
- HDU 3416 Marriage Match IV (最短路径&&最大流)
/*题意: 有 n 个城市,知道了起点和终点,有 m 条有向边,问从起点到终点的最短路一共有多少条.这是一个有向图,建边的时候要注意!!解题思路:这题的关键就是找到哪些边可以构成最短路,其实之前做最短 ...
- 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
最短路+最大流 #include<cstdio> #include<cstring> #include<string> #include<cmath> ...
- HDU 3416 Marriage Match IV 【最短路】(记录路径)+【最大流】
<题目链接> 题目大意: 给你一张图,问你其中没有边重合的最短路径有多少条. 解题分析: 建图的时候记得存一下链式后向边,方便寻找最短路径,然后用Dijkstra或者SPFA跑一遍最短路, ...
- 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 ...
随机推荐
- Java Swing编程接口(30)---列表框:JList
列表框同时可以在信息呈现给用户的列表多个选项,使用JList能够建立一个列表框. package com.beyole.util; import java.awt.Container; import ...
- WPF 左键单击弹出菜单 ContextMenu
原文:WPF 左键单击弹出菜单 ContextMenu WPF中的ContextMenu在XAML中可直接做出来,但是仅限于右键弹出菜单,如果需要添加左键弹出功能,只需要在事件中添加Click事件 X ...
- WPF——TargetNullValue(如何在绑定空值显示默认字符)
原文:WPF--TargetNullValue(如何在绑定空值显示默认字符) 说明:在数据绑定时,如果有些字段为空值,那么在数据绑定时可以用默认值来显示为空的字段. </Grid> { L ...
- QML中文件的加载(三种方法)
在这里小小总结一下QML文件中如何加载QML文件与JavaScript文件. 1.QML文件中加载JavaScript文件 语法: import <ModuleIdentifier> &l ...
- 图像滤镜艺术---Hudson滤镜(Instagram)
原文:图像滤镜艺术---Hudson滤镜(Instagram) 今天给大家实现的是Instagram中的Hudson滤镜,为什么介绍Instagram滤镜,原因很简单,Instagram本身就 ...
- 8086 CPU 寄存器简介(超详细,图文并茂)
http://www.cnblogs.com/BoyXiao/archive/2010/11/20/1882716.html
- ArchLinux 安装记录
主要步骤 下载镜像及刻录 开机安装 联网 编辑镜像站文件 分区 格式化分区并挂载 安装基本操作系统 配置基础操作系统 引导系统 用户管理 网络配置 安装Gonme桌面环境 其他优化 开始准备 下载镜像 ...
- Qt DLL总结【二】-创建及调用QT的 DLL(三篇)good
目录 Qt DLL总结[一]-链接库预备知识 Qt DLL总结[二]-创建及调用QT的 DLL Qt DLL总结[三]-VS2008+Qt 使用QPluginLoader访问DLL 开发环境:VS20 ...
- Qt Style Sheet实践(二):组合框QComboBox的定制(24K纯开源)——非常漂亮
组合框是一个重要且应用广泛的组件,一般由两个子组件组成:文本下拉单部分和按钮部分.在许多既需要用户选择.又需要用户手动输入的应用场景下,组合框能够很好的满足我们的需求.如我们经常使用的聊天软件QQ登录 ...
- 搜索栏+collectionView实现
效果图如下: 1.h文件声明方法: @interface IDSGameRoomSearchPage : UIView @property (nonatomic,weak) BaseVie ...