题目大意:在城市A的男孩想去城市B的女孩,不过他去城市B必须走最短路,并且走过的路不可以再走,问他最多能看这个女孩多少次。
 
分析:因为这个男孩直走最短路,所以我们必须求出来所有最短路径上的路,怎么判断一条路是否属于最短路经上的呢?其实比较容易的,只要先求出来从A到达所有点的最短路distA[x], 然后再求出来所有点到B的最短路distB[y](添加反边从B开始即可求出),如果x-y之间有一条路,那么只需要判断distA[x]+distB[y]+w(x,y) == distA[B] 是否成立即可。然后把这条边加入新图中,流量置为1(因为只可以走1次),求出来从源点到汇点的最大流就是所求结果。
注意:可能会爆栈。
下面是AC代码。
========================================================================================================================
#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<vector>
using namespace std; const int MAXN = 1e6+;
const int MAXM = ;
const int oo = 1e9+;
///分别存正向图,反向图,和重构图
struct Edge{int v, val, next;}ss[MAXN], ee[MAXN], edge[MAXN<<];
int Hs[MAXM], He[MAXM], Head[MAXM], cnt_s, cnt_e, cnt;
int DistS[MAXM], DistE[MAXM];///分别是从源点到达每点的距离,和每点到达源点的距离
int Layer[MAXM];///分层 void InIt(int N)
{
cnt = cnt_e = cnt_s = ; memset(Hs, -, sizeof(Hs));
memset(He, -, sizeof(He));
memset(Head, -, sizeof(Head)); for(int i=; i<=N; i++)
DistE[i] = DistS[i] = oo;
}
void AddEdge(Edge e[], int head[], int &ct, int u, int v, int val)
{
e[ct].v = v;
e[ct].val = val;
e[ct].next = head[u];
head[u] = ct++;
}
void spfa(Edge e[], int head[], int dist[], int start)
{///求最短路
stack<int> sta;
bool instack[MAXM] = {};
dist[start] = ;
sta.push(start); while(sta.size())
{
int u = sta.top();sta.pop();
instack[u] = false; for(int j=head[u]; j!=-; j=e[j].next)
{
int v = e[j].v; if(dist[v] > dist[u]+e[j].val)
{
dist[v] = dist[u] + e[j].val; if(instack[v] == false)
{
instack[v] = true;
sta.push(v);
}
}
}
}
}
void BuildGraph(int u, int MinLen)
{///遍历所有的边,把输入最短路的边加入新图中
for(int j=Hs[u]; j!=-; j=ss[j].next)
{
int v = ss[j].v; if(v != -)
{
if(DistS[u] + DistE[v] + ss[j].val == MinLen)
{
AddEdge(edge, Head, cnt, u, v, );
AddEdge(edge, Head, cnt, v, u, );
} ss[j].v = -; BuildGraph(v, MinLen);
}
}
}
bool BFS(int start, int End)
{
memset(Layer, , sizeof(Layer));
Layer[start] = ;
queue<int> Q;
Q.push(start); while(Q.size())
{
int u = Q.front();Q.pop(); if(u == End)return true; for(int j=Head[u]; j!=-; j=edge[j].next)
{
int v = edge[j].v; if(Layer[v] == false && edge[j].val)
{
Layer[v] = Layer[u] + ;
Q.push(v);
}
}
} return false;
}
int DFS(int u, int MaxFlow, int End)
{
if(u == End)return MaxFlow; int uflow = ; for(int j=Head[u]; j!=-; j=edge[j].next)
{
int v = edge[j].v; if(Layer[u]+ == Layer[v] && edge[j].val)
{
int flow = min(MaxFlow-uflow, edge[j].val);
flow = DFS(v, flow, End); edge[j].val -= flow;
edge[j^].val += flow;
uflow += flow; if(uflow == MaxFlow)
break;
}
} if(uflow == )
Layer[u] = ; return uflow;
}
int Dinic(int start, int End)
{
int MaxFlow = ; while(BFS(start, End) == true)
MaxFlow += DFS(start, oo, End); return MaxFlow;
} int main()
{
int T; scanf("%d", &T); while(T--)
{
int N, M, u, v, val; scanf("%d%d", &N, &M);
InIt(N); while(M--)
{
scanf("%d%d%d", &u, &v, &val); if(u == v)continue; AddEdge(ss, Hs, cnt_s, u, v, val);
AddEdge(ee, He, cnt_e, v, u, val);
} int start, End; scanf("%d%d", &start, &End); spfa(ss, Hs, DistS, start);///求源点到所有点的距离
spfa(ee, He, DistE, End);///求所有点到汇点的最短距离
BuildGraph(start, DistS[End]);///构建新图 printf("%d\n", Dinic(start, End));
} return ;
}

O - Marriage Match IV - hdu 3416(最短路+最大流)的更多相关文章

  1. Marriage Match IV HDU - 3416(最短路 + 最大流)

    题意: 求有多少条最短路 解析: 正着求一遍最短路 得dis1 反着求一遍得 dis2   然后 遍历所有的边 如果  dis1[u] + dis2[v] + w == dis1[B], 则说明这是一 ...

  2. Marriage Match IV HDU - 3416

    题意 给你n个点,m条边,要求每条边只能走一次的S到T的最短路径的个数 题解 在我又WA又TLE还RE时,yyb大佬告诉我说要跑两遍SPFA,还说我写的一遍SPFA是错的,然而 啪啪打脸... 而且他 ...

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

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

  4. Q - Marriage Match IV (非重复最短路 + Spfa + 网络最大流Isap)

    Q - Marriage Match IV Do not sincere non-interference. Like that show, now starvae also take part in ...

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

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

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

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

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

    HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...

  8. Marriage Match IV(最短路+网络流)

    Marriage Match IV http://acm.hdu.edu.cn/showproblem.php?pid=3416 Time Limit: 2000/1000 MS (Java/Othe ...

  9. HDU3605:Marriage Match IV

    Marriage Match IV Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

随机推荐

  1. 【Python之旅】第六篇(七):开发简易主机批量管理工具

    [Python之旅]第六篇(七):开发简易主机批量管理工具 python 软件开发 Paramiko模块 批量主机管理 摘要: 通过前面对Paramiko模块的学习与使用,以及Python中多线程与多 ...

  2. python文档字符串

    #coding=utf-8 #文档字符串def d(i,j): """这个函数实现了一个乘法运算. 函数会返回一个乘法运算的结果.""" k ...

  3. 1、第1课.net学习2150916

    HTML标签 1.<p> <p> 标签 段落标签 2.<h1-6></h1> 文字标签从1-6 3. <i></i> 斜体 &l ...

  4. Jquery分步学习一

    <script type="text/javascript" src="../js/jquery-1.11.0.js"></script> ...

  5. asp.net 从客户端中检测到有潜在危险的 Request.Form 值错误解

    从客户端(ftbContent="<P><A href="http://l...")中检测到有潜在危险的 Request.Form 值. 说明: 请求验 ...

  6. Mac OS X 10.9 Mavericks 修改root密码

    Mac10.9忘记密码后有两种方式可以进去:  代码如下 复制代码 1.sudo passwd 重新输入密码即可,此方法修改了root的密码  代码如下 复制代码 2.sudo bash 输入当前用户 ...

  7. 【转】iOS开发系列--数据存取

    原文: http://www.cnblogs.com/kenshincui/p/4077833.html#SQLite 概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储 ...

  8. Objective-C中的内存管理——手动内存管理

    一.引用计数(retainCount) 1.内存的申请 alloc和new是Objective-C语言中申请内存的两种常用方式. 当我们向一个类对象发送一个alloc消息的时候,其会向操作系统在堆中申 ...

  9. NSURLConnection下载

    @interface AppDelegate () <NSURLConnectionDataDelegate> {    NSMutableData *mData;} @end @impl ...

  10. 在SpringMVC框架下建立Web项目时web.xml到底该写些什么呢?

    刚刚初学Spring MVC,却连一个简单的helloworld都搞的懵懵懂懂的,配置文件搞不清,各种文件之间的逻辑关系也不懂,连续看了好些日子的Spring MVC了,今天终于下定决心,每天记录一点 ...