href="http://ounix1xcw.bkt.clouddn.com/github.markdown.css" rel="stylesheet">
这是leetcode的第399题--Redundant Connection
题目 Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.
Example: Given a / b = 2.0, b / c = 3.0.
queries are:a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].
The input is: vector > equations, vector & values, vector > queries , where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector .
According to the example above:
equations = [ ["a", "b"], ["b", "c"] ], values = [2.0, 3.0], queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction. 思路 这道题由于是除法,会想到有向图,但是发现,a->b, c->b有可以推出a,b关系,所以连通即可。为了能方便搜索,我又增加了一条反向边vuy(代码第161行),当然权值为倒数,可是这样增加了深搜难度,于是要解决环的搜索问题(代码第127行)
show me the code
from collections import Iterable,deque class vertex: def __init__(self,mark,val=None ,firstEdge = None): self.mark = mark self.val = val self.firstEdge = firstEdge self.isVisited = False def __str__(self): if '0'<=self.mark[0]<='9':return 'v' str(self.mark) return str(self.mark) def __repr__(self): li=[] arc= self.firstEdge while arc!=None: li.append(arc) arc= arc.outNextEdge return str(self) ' to:' str([str(i.inArrow) for i in li]) class edge: def __init__(self,outArrow,inArrow,outNextEdge = None,inNextEdge = None, weight = 1): self.weight = weight self.inNextEdge = inNextEdge self.outNextEdge = outNextEdge self.outArrow = outArrow self.inArrow=inArrow self.isVisited = False def __str__(self): return '--' str(self.weight) '-->' def __repr__(self): return str(self) class graph: def __init__(self): self.vertexs = {} self.edges = {} def __getitem__(self,i): return self.vertexs[i] def __setitem__(selfi,x): self.vertexs[i]= x def __iter__(self): return iter(self.vertexs.values()) def __bool__(self): return len(self.vertexs)!=0 def addVertex(self,vertexs): '''vertexs is a iterable or just a mark that marks the vertex,whichc can be every imutable type''' if not isinstance(vertexs,Iterable):vertexs=[vertexs] for i in vertexs: if not isinstance(i,vertex) and i not in self.vertexs:self.vertexs[i]= vertex(i) if isinstance(i,vertex) and i not in self.vertexs:self.vertexs[i.mark]= i def isConnected(self,v,u): v = self.__getVertex(v) u = self.__getVertex(u) arc= v.firstEdge while arc!=None: if arc.inArrow==u:return True arc = arc.inNextEdge return False def __getVertex(self,v): if not isinstance(v,vertex): if v not in self.vertexs: self.vertexs[v]=vertex(v) return self.vertexs[v] return v def addEdge(self,v,u,weight = 1): v = self.__getVertex(v) u = self.__getVertex(u) arc = v.firstEdge while arc!=None: #examine that if v,u have been already connected if arc.inArrow==u: return arc= arc.outNextEdge newEdge = edge(v,u,v.firstEdge,u.firstEdge,weight) self.edges[(v.mark,u.mark)] = newEdge v.firstEdge = newEdge def delEdge(self,v,u): if not isinstance(v,vertex):v= self.vertexs[v] if not isinstance(u,vertex):u= self.vertexs[u] self._unrelated(v,u) del self.edges[(v.mark,u.mark)] def _unrelated(self,v,u): if v.firstEdge==None:return if v.firstEdge.inArrow == u: v.firstEdge =v.firstEdge.outNextEdge else: arc = v.firstEdge while arc.outNextEdge!=None: if arc.outNextEdge.inArrow ==u: arc.outNextEdge = arc.outNextEdge.outNextEdge break def revisit(self): for i in self.vertexs: self.vertexs[i].isVisited=False for i in self.edges: self.edges[i].isVisited=False def __str__(self): arcs= list(self.edges.keys()) arcs=[str(i[0]) '--->' str(i[1]) ' weight:' str(self.edges[i].weight) for i in arcs] s= '\n'.join(arcs) return s def __repr__(self): return str(self) def notIn(self,v): if (isinstance(v,vertex) and v.mark not in self.vertexs) or v not in self.vertexs: return True return False def visitPath(self,v,u): '''bfs''' if self.notIn(v) or self.notIn(u): return None,None v = self.__getVertex(v) u = self.__getVertex(u) if v.firstEdge==None:return None,None q=deque([v.firstEdge]) isFind=False vs,es=[],[] while len(q)!=0: vs,es=[],[] arc= q.popleft() if arc.outNextEdge!=None and not arc.outNextEdge.isVisited:q.append(arc.outNextEdge) while arc!=None: if arc.isVisited:break arc.isVisited=True es.append(arc) vs.append(arc.inArrow) arc.outArrow.isVisited=True if arc.inArrow==u: isFind=True break arc = arc.inArrow.firstEdge while arc.inArrow.isVisited and arc.outNextEdge:arc = arc.outNextEdge if isFind:break else:return None,None ''' se = [str(i) for i in es] sv = [str(i) for i in vs] print(str(v),end='') for i,j in zip(se,sv): print(i,j,end='') ''' return vs,es def hasVertex(self,mark): return mark in self.vertexs def display(self): print('vertexs') for i in self.vertexs: print(self.vertexs[i].__repr__()) print('edges') for i in self.edges: arc=self.edges[i] print(str(arc.outArrow) str(arc) str(arc.inArrow)) class Solution(object): def calcEquation(self, equations, values, queries): """ :type equations: List[List[str]] :type values: List[float] :type queries: List[List[str]] :rtype: List[float] """ rst =[] g= graph() for edge,wt in zip(equations,values): g.addEdge(edge[0],edge[1],wt) g.addEdge(edge[1],edge[0],1/wt)###### to serach quickly but sacrifacing some space g.display() for i in queries: if i[0]==i[1]: if i[0] in g.vertexs:rst.append(1.0) else:rst.append(-1.0) continue _,path = g.visitPath(i[0],i[1]) if path==None: if not path:rst.append(-1.0) else: mul = 1 for i in path:mul*=i.weight rst.append(mul) g.revisit() return rst