<题目链接>

题目大意:

给你一张图,问你其中没有边重合的最短路径有多少条。

解题分析:

建图的时候记得存一下链式后向边,方便寻找最短路径,然后用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 【最短路】(记录路径)+【最大流】的更多相关文章

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

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

  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 (最短路径,网络流,最大流)

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

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

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

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

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

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

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

  7. hdu 3416 Marriage Match IV 【 最短路 最大流 】

    求边不可重复的最短路条数 先从起点到终点用一次dijkstra,再从终点到起点用一次dijkstra,来判断一条边是否在最短路上 如果在,就将这条边的两个端点连起来,容量为1 再跑一下dinic(), ...

  8. HDU 3416 Marriage Match IV dij+dinic

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

  9. HDU 3416 Marriage Match IV

    最短路+最大流 #include<cstdio> #include<cstring> #include<string> #include<cmath> ...

随机推荐

  1. pytorch的学习资源

    安装:https://github.com/pytorch/pytorch 文档:http://pytorch.org/tutorials/beginner/blitz/tensor_tutorial ...

  2. nodejs之koa-router与koa-body搭配使用

    简介 koa需要搭配中间件来做接口更方便,使用Koa-body & Koa-router 使用 koa2 创建接口,处理post请求 const koa=require("koa&q ...

  3. django中数据库的配置及相关增删改查

    ORM ORM是什么?:(在django中,根据代码中的类自动生成数据库的表也叫--code first) ORM:Object Relational Mapping(关系对象映射) 类名对应---- ...

  4. selenium 获取input输入框中的值的方法

    方法一:获取input的文本值 <input class="form-text-normal" id="txtName" name="Name& ...

  5. asynicio模块以及爬虫应用asynicio模块(高性能爬虫)

    一.背景知识 爬虫的本质就是一个socket客户端与服务端的通信过程,如果我们有多个url待爬取,只用一个线程且采用串行的方式执行,那只能等待爬取一个结束后才能继续下一个,效率会非常低. 需要强调的是 ...

  6. Decimal integer conversion

    问题 : Decimal integer conversion 时间限制: 1 Sec  内存限制: 128 MB 题目描述 XiaoMing likes mathematics, and he is ...

  7. C++ Primer 笔记——union

    1.union是一种特殊的类.一个union可以有多个数据成员,但是在任意时刻,只有一个数据成员可以有值.当我们给union的某个成员赋值之后,该union的其他成员就变成未定义的状态了.分配给一个u ...

  8. IDEA抛出No bean named 'cacheManager' available解决方法

    (正确的,老师发我的) <?xml version="1.0" encoding="UTF-8"?><beans xmlns="ht ...

  9. How does exercise keep your brain young?

    Exercise may protect the brain from disease and dementia as we age, but the mechanisms behind its be ...

  10. Aws云服务EMR使用

    Aws云服务EMR使用 创建表结构 创建abc库下的abc_user_i表字段s3://abc-server/abc-emr/shell/ABC_USER_HIVE.q: EXTERNAL 指定为外部 ...