• SGU 185 Two shortest (最大流)


    题目:

    http://acm.sgu.ru/problem.php?contest=0&problem=185

    题意:

    给你一个无向图,让你找两条不相交的从1到n的最短路径,并输出

    注意:

    卡内存,需要用short存数据,否则MLE

    方法:

    首先从1跑最短路

    然后用最大流判是否两条不相交的最短路

    然后用dfs输出路径

    建图:

    从源点向起点1建边$(S,u,2)$,表示流两条路径

    从1跑完最短路后,对于任意顶点u,v,如果$d[u]+g[u][v]==d[v]$,则建边$(u,v,1)$,表示边$(u,v)$只能用一次

     1 void build()
     2 {
     3     spfa(1);
     4     dinic.init(n + 2);
     5     dinic.st = 0;
     6     dinic.ed = n;
     7     dinic.adde(dinic.st, 1, 2);
     8     for (int i = 1; i <= n; i++)
     9         for (int j = 1; j <= n; j++)
    10             if (d[i] + g[i][j] == d[j])
    11                 dinic.adde(i, j, 1);
    12 }

    然后从S到顶点n跑最大流,如果流量为2,则有解,否则无解

    打印路径:

    从顶点1开始dfs,如果此边流满且未标记,则输出顶点,并标记此边

    做两次上述打印路径的过程

     1 void dfsout(int u)
     2 {
     3     if (u == ed)
     4     {
     5         printf("%d
    ", u);
     6         return;
     7     }
     8     printf("%d ", u);
     9     for (int i = head[u]; ~i; i = edge[i].next)
    10     {
    11         if (i & 1) continue;
    12         if (edge[i].cap == edge[i].flow)
    13         {
    14             edge[i].cap++;
    15             dfsout(edge[i].v);
    16             break;
    17         }
    18     }
    19 }
     1 void solve()
     2 {
     3     build();
     4     if (d[n] == inf || dinic.Dinic(inf) != 2)
     5     {
     6         puts("No solution");
     7         return;
     8     }
     9     dinic.dfsout(1);
    10     dinic.dfsout(1);
    11 }

    代码:

      1 /********************************************
      2 *ACM Solutions
      3 *
      4 *@Title: SGU 185 Two shortest
      5 *@Version: 1.0
      6 *@Time: 2014-08-28
      7 *@Solution: http://www.cnblogs.com/xysmlx/p/xxxxxxx.html
      8 *
      9 *@Author: xysmlx(Lingxiao Ma)
     10 *@Blog: http://www.cnblogs.com/xysmlx
     11 *@EMail: xysmlx@163.com
     12 *
     13 *Copyright (C) 2011-2015 xysmlx(Lingxiao Ma)
     14 ********************************************/
     15 // #pragma comment(linker, "/STACK:102400000,102400000")
     16 #include <cstdio>
     17 #include <iostream>
     18 #include <cstring>
     19 #include <string>
     20 #include <cmath>
     21 #include <set>
     22 #include <list>
     23 #include <map>
     24 #include <iterator>
     25 #include <cstdlib>
     26 #include <vector>
     27 #include <queue>
     28 #include <stack>
     29 #include <algorithm>
     30 #include <functional>
     31 using namespace std;
     32 typedef long long LL;
     33 #define pb push_back
     34 #define ROUND(x) round(x)
     35 #define FLOOR(x) floor(x)
     36 #define CEIL(x) ceil(x)
     37 const int maxn = 510;
     38 const int maxm = 200010;
     39 const short inf16 = 0x3f3f;
     40 const int inf = 0x3f3f3f3f;
     41 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
     42 const double INF = 1e30;
     43 const double eps = 1e-6;
     44 const int P[4] = {0, 0, -1, 1};
     45 const int Q[4] = {1, -1, 0, 0};
     46 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
     47 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
     48 
     49 short g[maxn][maxn];
     50 int n, m;
     51 int d[maxn];
     52 bool spfa(int s)
     53 {
     54     bool mark[maxn];
     55     queue<int> Q;
     56     memset(d, 0x3f, sizeof(d));
     57     memset(mark, 0, sizeof(mark));
     58     d[s] = 0;
     59     Q.push(s);
     60     mark[s] = 1;
     61     while (Q.size())
     62     {
     63         int u = Q.front();
     64         Q.pop();
     65         mark[u] = 0;
     66         for (int v = 1; v <= n; v++)
     67         {
     68             int w = g[u][v];
     69             if (w >= inf16) continue;
     70             if (d[u] + w < d[v])
     71             {
     72                 d[v] = d[u] + w;
     73                 if (mark[v] == 0)
     74                 {
     75                     mark[v] = 1;
     76                     Q.push(v);
     77                 }
     78             }
     79         }
     80     }
     81     return true;
     82 }
     83 
     84 struct DINIC
     85 {
     86     struct Edge
     87     {
     88         int u, v;
     89         short cap, flow;
     90         int next;
     91     } edge[maxm];
     92     int head[maxn], en; //需初始化
     93     int n, m, d[maxn], cur[maxn];
     94     int st, ed;
     95     bool vis[maxn];
     96     void init(int _n = 0)
     97     {
     98         n = _n;
     99         memset(head, -1, sizeof(head));
    100         en = 0;
    101     }
    102     void addse(int u, int v, int cap, int flow)
    103     {
    104         edge[en].u = u;
    105         edge[en].v = v;
    106         edge[en].cap = cap;
    107         edge[en].flow = flow;
    108         edge[en].next = head[u];
    109         head[u] = en++;
    110         cur[u] = head[u];
    111     }
    112     void adde(int u, int v, int cap)
    113     {
    114         addse(u, v, cap, 0);
    115         addse(v, u, 0, 0); //注意加反向0 边
    116     }
    117     bool BFS()
    118     {
    119         queue<int> Q;
    120         memset(vis, 0, sizeof(vis));
    121         Q.push(st);
    122         d[st] = 0;
    123         vis[st] = 1;
    124         while (!Q.empty())
    125         {
    126             int u = Q.front();
    127             Q.pop();
    128             for (int i = head[u]; i != -1; i = edge[i].next)
    129             {
    130                 int v = edge[i].v;
    131                 int w = edge[i].cap - edge[i].flow;
    132                 if (w > 0 && !vis[v])
    133                 {
    134                     vis[v] = 1;
    135                     Q.push(v);
    136                     d[v] = d[u] + 1;
    137                     if (v == ed) return 1;
    138                 }
    139             }
    140         }
    141         return false;
    142     }
    143     int Aug(int u, int a)
    144     {
    145         if (u == ed) return a;
    146         int aug = 0, delta;
    147         for (int &i = cur[u]; i != -1; i = edge[i].next)
    148         {
    149             int v = edge[i].v;
    150             int w = edge[i].cap - edge[i].flow;
    151             if (w > 0 && d[v] == d[u] + 1)
    152             {
    153                 delta = Aug(v, min(a, w));
    154                 if (delta)
    155                 {
    156                     edge[i].flow += delta;
    157                     edge[i ^ 1].flow -= delta;
    158                     aug += delta;
    159                     if (!(a -= delta)) break;
    160                 }
    161             }
    162         }
    163         if (!aug) d[u] = -1;
    164         return aug;
    165     }
    166     int Dinic(int NdFlow)
    167     {
    168         int flow = 0;
    169         while (BFS())
    170         {
    171             memcpy(cur, head, sizeof(int) * (n + 1));
    172             flow += Aug(st, inf);
    173             /*如果超过指定流量就return 掉*/
    174             if (NdFlow == inf) continue;
    175             if (flow > NdFlow) break;
    176         }
    177         return flow;
    178     }
    179 
    180     void dfsout(int u)
    181     {
    182         if (u == ed)
    183         {
    184             printf("%d
    ", u);
    185             return;
    186         }
    187         printf("%d ", u);
    188         for (int i = head[u]; ~i; i = edge[i].next)
    189         {
    190             if (i & 1) continue;
    191             if (edge[i].cap == edge[i].flow)
    192             {
    193                 edge[i].cap++;
    194                 dfsout(edge[i].v);
    195                 break;
    196             }
    197         }
    198     }
    199 } dinic;
    200 
    201 int kase;
    202 void init()
    203 {
    204     kase++;
    205     memset(g, 0x3f, sizeof(g));
    206 }
    207 void input()
    208 {
    209     for (int i = 0; i < m; i++)
    210     {
    211         int u, v, w;
    212         scanf("%d%d%d", &u, &v, &w);
    213         g[u][v] = g[v][u] = w;
    214     }
    215 }
    216 void debug()
    217 {
    218     //
    219 }
    220 void build()
    221 {
    222     spfa(1);
    223     dinic.init(n + 2);
    224     dinic.st = 0;
    225     dinic.ed = n;
    226     dinic.adde(dinic.st, 1, 2);
    227     for (int i = 1; i <= n; i++)
    228         for (int j = 1; j <= n; j++)
    229             if (d[i] + g[i][j] == d[j])
    230                 dinic.adde(i, j, 1);
    231 }
    232 void solve()
    233 {
    234     build();
    235     if (d[n] == inf || dinic.Dinic(inf) != 2)
    236     {
    237         puts("No solution");
    238         return;
    239     }
    240     dinic.dfsout(1);
    241     dinic.dfsout(1);
    242 }
    243 void output()
    244 {
    245     //
    246 }
    247 int main()
    248 {
    249     // int size = 256 << 20; // 256MB
    250     // char *p = (char *)malloc(size) + size;
    251     // __asm__("movl %0, %%esp
    " :: "r"(p));
    252 
    253     // std::ios_base::sync_with_stdio(false);
    254 #ifdef xysmlx
    255     freopen("in.cpp", "r", stdin);
    256 #endif
    257 
    258     kase = 0;
    259     while (~scanf("%d%d", &n, &m))
    260     {
    261         init();
    262         input();
    263         solve();
    264         output();
    265     }
    266     return 0;
    267 }
    SGU 185
  • 相关阅读:
    数据结构与算法
    c++学习笔记
    红黑树(map与unorder_map)B B+树
    数据库笔记
    多路复用IO:select poll epoll
    https加密过程!!! 这才是差不多非常详细的https双方获取共用的秘钥过程!!!!!
    助教周报(第一轮)——范青青
    第二十二周助教总结(2021.6.28-7.4)
    第二十一周助教总结(2021.6.21-6.27)
    第二十周助教总结(2021.6.14-6.20)
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3942341.html
Copyright © 2020-2023  润新知