FOJ 243. Paths

競程作業,2015 Competitive Programming I 期末考 Problem B:FOJ-243

他要每個點之間的東西,所以感覺就是要用 Floyd Warshall
而且我又在 Wiki 上面看到他說有經過負環的點 i 他的自己到自己的最短路徑會是負的
所以就用了

做完 Floyd Warshall 之後
在看任兩個有路徑點是不是其中一個會經過負環(也就是 (i, i) 小於零
有的話就是找到沒有最短路徑的了

但是
還有一種情況就是兩個點其中一個路徑上的點會有負環
為了解決這個情況我用了一個很噁心的方法
就是只要找到有負的點
就把它設成一個很醜的小數,最後只要看誰跟誰的之間是很醜的小數就是會經過負環了
然後我就亂寫,把 Floyd Warshall 作兩次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# include <bits/stdc++.h>
using namespace std;
# define ll long long
# define ui unsigned int
# define ull unsigned long long
# define INF 1023456789
# define jizz cin.tie(0);ios_base::sync_with_stdio(0);

void solve(){
int n, m, a, b, w, ans1=0, ans2=0, ans3=0;
cin>>n>>m;
vector<vector<double>> D(n+2, vector<double>(n+2, INF));

for(int i=1; i<=n; i++){
D[i][i] = 0;
}

for(int i=0; i<m; i++){
cin>>a>>b>>w;
if(w<D[a][b])
D[a][b] = w;
}

for(int i=1; i<=n; i++){
for(int u=1; u<=n; u++){
for(int v=1; v<=n; v++){
if(D[u][v]>D[u][i]+D[i][v]&&D[u][i]!=INF&&D[i][v]!=INF){
D[u][v] = D[u][i] + D[i][v];
}
if(u==v&&D[u][v]<0) D[u][v]-=1.0/3.32;
}
}
}
for(int i=1; i<=n; i++){
for(int u=1; u<=n; u++){
for(int v=1; v<=n; v++){
if(D[u][v]>D[u][i]+D[i][v]&&D[u][i]!=INF&&D[i][v]!=INF){
D[u][v] = D[u][i] + D[i][v];
}
if(u==v&&D[u][v]<0) D[u][v]-=1.0/3.32;
}
}
}
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(D[i][j]==INF){
ans1++;
}
else if(D[i][i]<0||D[j][j]<0){
if(D[i][j]!=INF){
ans2++;
}
}
else if(D[i][j]!=(int)D[i][j]){
ans2++;
}
else if(D[i][j]!=INF){
ans3++;
}
}
}
cout<<ans1<<" "<<ans2<<" "<<ans3<<"\n";
}

int main(){
int t;
cin>>t;
while(t--){
solve();
}
}