競程作業,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(); } }
|