zoukankan      html  css  js  c++  java
  • HUD3416 Marriage Match IV

    胡扯

    看到这道题写最短路也写网络流,正好拿过来写写

    难度很低,大佬轻喷/kk

    思路

    最短路可行边+网络最大流

    手残写错了几个地方调了半个上午

    题意就是找题目给定起点终点之间最短路的条数。

    有一个很显然的性质,设起点为 (s), 终点为 (t)(dis_{u,v}) 表示 (u)(v) 的最短路,(val_{x,y}) 表示边 ((x,y)) 的长度,则对于一条可以在最短路上的边((x,y)),一定有 (dis_{s,x}+val_{x,y}+dis_{y,t}=dis_{s,t})

    有了这个性质,我们就可以将最短路上的边重新建图,边的流量为 (1),然后在图上跑最大流,得到的最大流就是最短路的条数。

    求最短路可以用 (Dij) 跑出 (s) 到每个点的最短路,同时建反向边,跑出 (t) 到每个点的最短路(实际上是每个点到 (t) 的最短路),再进行上述判断即可。

    重边不用判,因为说不定这条重边也可以在最短路上。

    代码

    注释不删了,好让自己明白自己有多菜

    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 2e3 + 11;
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
      char c = getchar();
      int x = 0, f = 1;
      for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
      for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
      return x * f;
    }
    
    struct edge { int to, nxt, val; } e[A << 1];
    int n, m, cnt, flag[B][B], endd, head[2][A], dis[2][A], vis[A];
    
    inline void add(int tg, int from, int to, int val) {
      e[++cnt].to = to;
      e[cnt].val = val;
      e[cnt].nxt = head[tg][from];
      head[tg][from] = cnt;
    }
    
    struct node {
      int x, y;
      bool operator < (const node &b) const {
        return y > b.y;
      }
    };
    
    inline void Dij(int s, int tg) {
      priority_queue <node> Q;
      while (!Q.empty()) Q.pop();
      memset(vis, 0, sizeof(vis));
      memset(dis[tg], inf, sizeof(dis[tg]));
      dis[tg][s] = 0;
      Q.push((node){s, 0});
      while (!Q.empty()) {
        int now = Q.top().x; Q.pop();
        if (vis[now]) continue;
        vis[now] = 1;
        for (int i = head[tg][now]; i; i = e[i].nxt) {
          int to = e[i].to;
          if (dis[tg][now] + e[i].val < dis[tg][to]) {
            dis[tg][to] = dis[tg][now] + e[i].val;
            Q.push((node){to, dis[tg][to]});
          }
        }
      }
    //  for (int i = 1; i <= n; i++) cout << dis[tg][i] << " ";
    //  puts("");
    }
    
    struct Max_flow {
      struct edge { int to, nxt, val; } edd[A << 1];
      int ccnt = 1, cur[A], inq[A], dep[A], hdd[A], vis[A];
      
      inline void init() {
        ccnt = 0;
        memset(hdd, 0, sizeof(hdd));
        memset(cur, 0, sizeof(cur));
      }
      
      inline void add(int from, int to, int val) {
        edd[++ccnt].to = to;
        edd[ccnt].val = val;
        edd[ccnt].nxt = hdd[from];
        hdd[from] = ccnt;
      }
      
      inline bool bfs(int s, int t) {
        queue <int> Q;
        for (int i = 1; i <= n; i++) 
          cur[i] = hdd[i], dep[i] = inf, inq[i] = 0;
        Q.push(s), dep[s] = 0, inq[s] = 1;
        while (!Q.empty()) {
          int x = Q.front(); Q.pop(), inq[x] = 0;
          for (int i = hdd[x]; i; i = edd[i].nxt) {
            int to = edd[i].to;
            if (dep[x] + 1 < dep[to] && edd[i].val) {
              dep[to] = dep[x] + 1;
              if (!inq[to]) Q.push(to), inq[to] = 1;
            }
          }
        }
        return dep[t] != inf;
      }
      
      int dfs(int x, int flow) {
        if (x == endd) return flow;
        for (int i = cur[x], tmp = 0; i; i = edd[i].nxt) {
          cur[x] = i;
          int to = edd[i].to;
          if (dep[to] == dep[x] + 1 && edd[i].val) {
            if (tmp = dfs(to, min(edd[i].val, flow))) {
              edd[i].val -= tmp, edd[i ^ 1].val += tmp;
              return tmp;
            }
          }
        }
        return 0;
      }
    } Flow;
    
    inline void solve() {
      memset(flag, 0, sizeof(flag));
      memset(head, 0, sizeof(head));
      Flow.init();
      cnt = 0;
      n = read(), m = read();
      int tot = 0;
      for (int i = 1; i <= m; i++) {
        int u = read(), v = read(), w = read();
        add(0, u, v, w);
        add(1, v, u, w);
      }
      int s = read(), t = read();
      Dij(s, 0), Dij(t, 1);
    //  for (int i = 1; i <= n; i++) {
    //    for (int j = 1; j <= n; j++) {
    //      cout << flag[i][j] << " ";
    //    }
    //    puts("");
    //  }
      for (int i = 1; i <= n; i++) {
        for (int j = head[0][i]; j; j = e[j].nxt) {
    //      cout << "ij " << i << " " << e[j].to << " ";
    //      cout << dis[0][i] << " " << e[j].val << " " << dis[1][e[j].to] << " " << dis[0][t] << '
    ';
          if (dis[0][i] + e[j].val + dis[1][e[j].to] == dis[0][t]) {
            Flow.add(i, e[j].to, 1);
            Flow.add(e[j].to, i, 0);
          }
        }
      }
      endd = t;
      int ans = 0, now = 0;
    //  cout << Flow.ccnt << '
    ';
      while (Flow.bfs(s, t)) while (now = Flow.dfs(s, inf)) ans += now;
      cout << ans << '
    ';
      return;
    }
    
    signed main() {
      int T = read();
      while (T--) solve();
    }
    
  • 相关阅读:
    【转-整理】win764bit plsql 登录oracle11g ora-12154 问题汇总
    【转-整理】log4j 简单解释,配置
    sparsity and density
    转:Recsys2013论文导读
    学院研究生论坛-如何做研究
    推荐系统开源软件列表
    linux下如何用GDB调试c++程序
    全国大学生数据挖掘邀请赛中的NDCG
    网络科学自学资料
    科普文:从人人网看网络科学(Network Science)的X个经典问题
  • 原文地址:https://www.cnblogs.com/loceaner/p/13837118.html
Copyright © 2011-2022 走看看