object Main extends App {
  import scala.io.StdIn.readLine
  val Array(studentNum, constraintNum) = readLine().split(' ').map(_.toInt)
  implicit val students = Student(studentNum)
  for (_ ← 0 until constraintNum){
    parseConstraint(readLine().trim().toList)
  }
  println(searchMax(students) match{
    case Some(m) if m == Int.MaxValue ⇒ "inf"
    case Some(m) ⇒ m
    case _ ⇒ -1
  })
  def searchMax(student:Array[Student]):Option[Int] = {
    var max = 0
    var hasRoute = false
    val memo = Array.tabulate(student.size){_ ⇒ Int.MaxValue}
    memo(0) = 0
    for (selector ← Student.validSelectors){
      var count = 0
      var isRenew = true
      while (count <= student.size && isRenew) {
        isRenew = false
        for (s ← student) {
          if (memo(s.id - 1) != Int.MaxValue) {
            for (Relation(to, distance) ← s.Relations(selector)) {
              if (memo(to.id - 1) > memo(s.id - 1) + distance) {
                memo(to.id - 1) = memo(s.id - 1) + distance
                isRenew = true
              }
            }
          }
        }
        count += 1
      }
      if (count <= student.size) {
        hasRoute = true
        if (max < memo.max)
          max = memo.max
      }
      memo.indices.foreach(memo(_) = Int.MaxValue)
      memo(0) = 0
    }
    if (hasRoute) Some(max)
    else None
  }
  def parseConstraint(str:List[Char])(implicit students:Array[Student]):Unit = {
    str match{
      case (a FasterThan b) & NearThan(d) ⇒
        Student.FasterAndNear(students(a - 1), students(b - 1), d)
      case (a FasterThan b) & FarThan(d) ⇒
        Student.FasterAndFar(students(a - 1), students(b - 1), d)
      case (a LaterThan b) & NearThan(d) ⇒
        Student.LaterAndNear(students(a - 1), students(b - 1), d)
      case (a LaterThan b) & FarThan(d) ⇒
        Student.LaterAndFar(students(a - 1), students(b - 1), d)
      case (a NoOrder b) & NearThan(d) ⇒
        Student.NoOrderAndNear(students(a - 1), students(b - 1), d)
      case (a NoOrder b) & FarThan(d) ⇒
        Student.NoOrderAndFar(students(a - 1), students(b - 1), d)
      case _ ⇒ ???
    }
  }
}
class Student private (val id:Int){
  private var mRelation:List[Relation] = Nil
  private var mSelectableRelation:List[Int ⇒ Option[Relation]] = Nil
  private def addRelation(to:Student, distance:Int):Unit = {
    mRelation ::= Relation(to, distance)
  }
  private def addSelectableRelation(selector:Int ⇒ Boolean, to:Student, distance:Int):Unit = {
    val relation = Some(Relation(to, distance))
    mSelectableRelation ::= {n:Int ⇒ if (selector(n)) relation else None}
  }
  def Relations(implicit selector:Int):List[Relation] = mSelectableRelation.flatMap{f ⇒ f(selector)} ++ mRelation
}
object Student{
  private var noOrderConstrain:Int = 0
  def FasterAndNear(a:Student, b:Student, d:Int): Unit = {
    a.addRelation(b, d)
    b.addRelation(a, 0)
  }
  def FasterAndFar(a:Student, b:Student, d:Int):Unit = {
    b.addRelation(a, -d)
  }
  def LaterAndNear(a:Student, b:Student, d:Int):Unit = {
    a.addRelation(b, 0)
    b.addRelation(a, d)
  }
  def LaterAndFar(a:Student, b:Student, d:Int):Unit = {
    a.addRelation(b, -d)
  }
  def NoOrderAndNear(a:Student, b:Student, d:Int):Unit = {
    val current = noOrderConstrain
    a.addSelectableRelation({n ⇒ (n & (1 << current)) != 0}, b, d)
    b.addSelectableRelation({n ⇒ (n & (1 << current)) == 0}, a, d)
    noOrderConstrain += 1
  }
  def NoOrderAndFar(a:Student, b:Student, d:Int):Unit = {
    val current = noOrderConstrain
    a.addSelectableRelation({n ⇒ (n & (1 << current)) != 0}, b, d)
    b.addSelectableRelation({n ⇒ (n & (1 << current)) == 0}, a, d)
    noOrderConstrain += 1
  }
  def apply(size:Int):Array[Student] = {
    val res = Array.tabulate(size){n ⇒ new Student(n + 1)}
    for (i ← 1 until size){
      res(i).addRelation(res(0), 0)
    }
    res
  }
  def validSelectors:Range = 0 until (1 << noOrderConstrain)
}
case class Relation(otherStudent:Student, distance:Int)
object Id{
  def unapply(arg: List[Char]): Option[(Int, List[Char])] = arg match{
    case n Digits r ⇒ Some(n.mkString.toInt, r)
    case _ ⇒ None
  }
  private object Digits{
    def unapply(arg: List[Char]): Option[(List[Char], List[Char])] = arg  match{
      case h::t if h.isDigit ⇒
        t match{
          case n Digits r ⇒ Some(h::n, r)
          case _ ⇒ Some(List(h), t)
        }
      case _ ⇒ None
    }
  }
}
object Number{
  def unapply(arg: List[Char]): Option[(Int, List[Char])] = arg match{
    case n Id r ⇒ Some(n, r)
    case _ ⇒ None
  }
}
object FasterThan{
  def unapply(arg: List[Char]): Option[(Int, Int)] = arg match{
    case a Id '<'::'='::(b Id _)⇒ Some(a, b)
    case _ ⇒ None
  }
}
object LaterThan{
  def unapply(arg: List[Char]):Option[(Int, Int)] = arg match{
    case a Id '>'::'='::(b Id _) ⇒ Some(a, b)
    case _ ⇒ None
  }
}
object NoOrder{
  def unapply(arg: List[Char]): Option[(Int, Int)] = arg match{
    case a Id '*'::(b Id _) ⇒ Some(a, b)
    case _ ⇒ None
  }
}
object NearThan{
  def unapply(arg:List[Char]):Option[Int] = arg match {
    case '-'::(n Number _) ⇒ Some(n)
    case _::t ⇒ unapply(t)
    case Nil ⇒ None
  }
}
object FarThan{
  def unapply(arg: List[Char]): Option[Int] = arg match{
    case '+'::(n Number _) ⇒ Some(n)
    case _::t ⇒ unapply(t)
    case _ ⇒ None
  }
}
object &{
  def unapply[T](arg: T): Option[(T, T)] = Some(arg, arg)
}
