标签:范围 ++i 倍增 log floyed string family get font
负环
【问题描述】
【输入格式】
【输出格式】
【样例输入】
3 6
1 2 -2
2 1 1
2 3 -10
3 2 10
3 1 -10
1 3 10
【样例输出】
2
【数据范围】
题解:
主要算法:最短路(Floyed);倍增;
考虑二分最小点数,用 Floyed (用倍增来限制步数)检验答案的范围区间
那么将二分过程化为倍增的过程,可行时不断缩小答案,否则继承当前答案
1 #include<cmath>
2 #include<cstdio>
3 #include<cstdlib>
4 #include<cstring>
5 #include<iostream>
6 #include<algorithm>
7 using namespace std;
8 const int maxn = 301;
9 const int logn = 6;
10 inline int Get()
11 {
12 int x;
13 char c;
14 bool o = false;
15 while((c = getchar()) < ‘0‘ || c > ‘9‘)
16 if(c == ‘-‘) o = true;
17 x = c - ‘0‘;
18 while((c = getchar()) >= ‘0‘ && c <= ‘9‘)
19 x = x * 10 + c - ‘0‘;
20 return (o) ? -x : x;
21 }
22 int n, m;
23 int f[maxn][maxn][logn + 1], g[maxn][maxn], s[maxn][maxn];
24 inline void Clear()
25 {
26 memset(f, 127 / 2, sizeof(f));
27 for(int k = 0; k <= logn; ++k)
28 for(int i = 1; i <= n; ++i)
29 f[i][i][k] = 0;
30 memset(s, 127 / 2, sizeof(s));
31 for(int i = 1; i <= n; ++i) s[i][i] = 0;
32 }
33 int main()
34 {
35 n = Get(), m = Get();
36 Clear();
37 for(int i = 1; i <= m; ++i)
38 {
39 int x = Get(), y = Get(), z = Get();
40 f[x][y][0] = z;
41 }
42 for(int l = 1; l <= logn; ++l)
43 for(int i = 1; i <= n; ++i)
44 for(int j = 1; j <= n; ++j)
45 for(int k = 1; k <= n; ++k)
46 f[i][j][l] = min(f[i][j][l], f[i][k][l - 1] + f[k][j][l - 1]);
47 int ans = 1;
48 for(int l = logn; l >= 0; --l)
49 {
50 memcpy(g, s, sizeof(g));
51 for(int i = 1; i <= n; ++i)
52 for(int j = 1; j <= n; ++j)
53 for(int k = 1; k <= n; ++k)
54 s[i][j] = min(s[i][j], g[i][k] + f[k][j][l]);
55 bool flag = false;
56 for(int i = 1; i <= n; ++i)
57 if(s[i][i] < 0)
58 {
59 flag = true;
60 break;
61 }
62 if(flag) memcpy(s, g, sizeof(s));
63 else ans += (1 << l);
64 }
65 if(ans > n) printf("0\n");
66 else printf("%d\n", ans);
67 }
标签:范围 ++i 倍增 log floyed string family get font
原文地址:http://www.cnblogs.com/lytccc/p/6616625.html