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\n", 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\n", 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\n" :: "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

 

转载于:https://www.cnblogs.com/xysmlx/p/3942341.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值