-
-
Save rblaze/4563612 to your computer and use it in GitHub Desktop.
Специальная олимпиада-2: Bellman-Ford algorithm как первый шаг Johnson algorithm
Изначальная версия: haskell - 60 минут, C - две минуты.
Данные для обработки: http://spark-public.s3.amazonaws.com/algo2/datasets/large.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
const int infinity = 2147483647; | |
struct edge_t { | |
int v1; | |
int v2; | |
int cost; | |
}; | |
int | |
main(void) { | |
int nvertex, nedge; | |
scanf("%d %d\n", &nvertex, &nedge); | |
int nalledges = nedge + nvertex; | |
struct edge_t *edges = malloc(nalledges * sizeof(struct edge_t)); | |
// read input | |
for (int i = 0; i < nedge; i++) { | |
scanf("%d %d %d\n", &edges[i].v1, &edges[i].v2, &edges[i].cost); | |
} | |
// add edges from fake vertex | |
for (int i = 0; i < nvertex; i++) { | |
int idx = nedge + i; | |
edges[idx].v1 = 0; | |
edges[idx].v2 = i + 1; | |
edges[idx].cost = 0; | |
} | |
int *c1 = malloc((nvertex + 1) * sizeof(int)); | |
int *c2 = malloc((nvertex + 1) * sizeof(int)); | |
c1[0] = 0; | |
for (int i = 1; i < nvertex + 1; i++) { | |
c1[i] = infinity; | |
} | |
for (int n = 0; n < nvertex + 2; n++) { | |
for (int i = 0; i < nalledges; i++) { | |
int target = edges[i].v2; | |
int newcost = c1[edges[i].v1]; | |
if (newcost != infinity) { | |
newcost += edges[i].cost; | |
} | |
if (newcost < c1[target]) { | |
c1[target] = newcost; | |
} | |
} | |
if (n == nvertex) { | |
memcpy(c2, c1, (nvertex + 1) * sizeof(int)); | |
} | |
} | |
/* | |
for (int i = 0; i < nvertex + 1; i++) { | |
printf("%d\n", c1[i]); | |
} | |
*/ | |
if (memcmp(c1, c2, (nvertex + 1) * sizeof(int))) { | |
printf("Cycle\n"); | |
} else { | |
int v = c1[0]; | |
for (int i = 1; i < nvertex + 1; i++) { | |
if (c1[i] < v) { | |
v = c1[i]; | |
} | |
} | |
printf("Shortest path %d\n", v); | |
} | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE BangPatterns #-} | |
module Main where | |
import Control.DeepSeq | |
import Data.Functor | |
import Data.Int | |
import Data.Vector.Unboxed ((//)) | |
import qualified Data.Vector.Unboxed as V | |
--import Debug.Trace | |
type Vertex = Int | |
type Dist = Int32 | |
type Edge = (Vertex, Vertex, Dist) | |
type EdgeVec = V.Vector Edge | |
type CostVec = V.Vector Dist | |
readEdge :: String -> Edge | |
readEdge s = let [v1, v2, w] = words s | |
in (read v1, read v2, read w) | |
bfStep :: EdgeVec -> CostVec -> CostVec | |
bfStep edges !prev = V.unsafeAccumulate min prev $ V.map mincost edges | |
where | |
mincost :: Edge -> (Int, Int32) | |
mincost (s, h, c) = (h, cost s c) | |
cost w c = let precost = prev `V.unsafeIndex` w | |
in if precost == maxBound then maxBound else precost + c | |
mkEdgeVec :: Int -> [String] -> EdgeVec | |
mkEdgeVec nvert inp = V.unfoldr step (nvert, inp) | |
where | |
step (n, s:xs) = Just (readEdge s, (n, xs)) | |
step (0, []) = Nothing | |
step (!n, []) = Just ((0, n, 0), (n - 1, [])) | |
main :: IO() | |
main = do | |
header:body <- lines <$> getContents | |
let nvert = read $ head $ words header | |
let edgelist = mkEdgeVec nvert body | |
let bfbase = V.replicate (nvert + 1) maxBound // [(0, 0)] | |
print $ edgelist `deepseq` "running" | |
let bfout = iterate (bfStep edgelist) bfbase !! nvert | |
let bfcheck = bfStep edgelist bfout | |
let hasCycle = V.any id $ V.zipWith (/=) bfout bfcheck | |
putStrLn $ if hasCycle then "Cycle" else show $ V.minimum bfout |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@rblaze было бы странно, если бы была существенная разница. accumulate пишет в мутабельный массив и фьюжн отрабатывает нормально: