DFS算法检测图中的周期

时间:2016-06-02 09:11:03

标签: algorithm graph depth-first-search

        class ViewController: UIViewController {
            var jsonObj:NSDictionary?
            var values = [AnyObject]()
            @IBOutlet weak var tableView:UITableView!

            override func viewDidLoad() {
                super.viewDidLoad()
                getData()
                saveInBD()
                NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.saved(_:)), name: "kContextSavedNotification", object: nil)
            }
   //Loding json data from a json file

           func getData(){
            if let path = NSBundle.mainBundle().pathForResource("countries", ofType: "json") {
            do {
            let data = try NSData(contentsOfURL: NSURL(fileURLWithPath: path), options: NSDataReadingOptions.DataReadingMappedIfSafe)


            do {
            jsonObj =  try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary

            } catch {
            jsonObj = nil;
            }


            } catch let error as NSError {
            print(error.localizedDescription)
            }
            } else {
            print("Invalid filename/path.")
            }
            }
           **Notification reciever**

            func saved(not:NSNotification){
                dispatch_async(dispatch_get_main_queue()) {
                    if let data  = DatabaseManager.sharedInstance.getAllNews(){
                        self.values = data
                        print(data.count)
                        self.tableView.reloadData()

                    }

                }
                }

            func saveInBD(){
                if jsonObj != nil {
                    guard let nameArray = jsonObj?["data#"] as? NSArray else{return}
                    DatabaseManager.sharedInstance.addNewsInBackGround(nameArray)
                }
            }
            //UIButton for re-saving data again

            @IBAction func reloadAxn(sender: UIButton) {
                saveInBD()
            }

    }


    **Database Manager Class**

    public class DatabaseManager{

        static  let sharedInstance = DatabaseManager()

        let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

        private init() {
        }

        func addNewsInBackGround(arr:NSArray)  {
            let jsonArray = arr
            let moc = managedObjectContext

            let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
            privateMOC.parentContext = moc

                privateMOC.performBlock {
                    for jsonObject in jsonArray {
                        let entity =  NSEntityDescription.entityForName("Country",
                            inManagedObjectContext:privateMOC)

                        let managedObject = NSManagedObject(entity: entity!,
                            insertIntoManagedObjectContext: privateMOC) as! Country

                        managedObject.name = jsonObject.objectForKey("name")as? String

                    }


                    do {
                        try privateMOC.save()

                        self.saveMainContext()

                        NSNotificationCenter.defaultCenter().postNotificationName("kContextSavedNotification", object: nil)
                    } catch {
                        fatalError("Failure to save context: \(error)")
                    }
                }

        }





        func getAllNews()->([AnyObject]?){
            let fetchRequest = NSFetchRequest(entityName: "Country")
            fetchRequest.resultType = NSFetchRequestResultType.DictionaryResultType

            do {
                let results =
                    try managedObjectContext.executeFetchRequest(fetchRequest)
                results as? [NSDictionary]
                if results.count > 0
                {
                    return results
                }else
                {
                    return nil
                }
            } catch let error as NSError {
                print("Could not fetch \(error), \(error.userInfo)")
                return nil
            }
        }

        func saveMainContext () {
            if managedObjectContext.hasChanges {
                do {
                    try managedObjectContext.save()
                } catch {
                    let nserror = error as NSError
                    print("Unresolved error \(nserror), \(nserror.userInfo)")
                }
            }
        }
    }

我正在尝试确定给定的图形是否是树。

我执行DFS并查找周期,如果检测到周期,则给定图形不是树。

然后我检查是否所有节点都被访问过,如果没有访问任何节点,那么给定的图形不是树

第一行输入是: n 然后是m行,表示连接两个节点的边缘

n是节点数 m是边数

示例输入:
3 2
1 2
2 3

这是一个SPOJ问题http://www.spoj.com/problems/PT07Y/,我得到了错误答案。但根据我的说法,DFS似乎是正确的。

1 个答案:

答案 0 :(得分:0)

所以我在评论中针对一些简单的测试用例检查了你的代码,似乎是

7 6
3 1
3 2
2 4
2 5
1 6
1 7

你应该得到YES作为答案,而你的程序给出NO。

在这种情况下,这就是邻居的样子:

1: 3 6 7 
2: 3 4 5 
3: 1 2 
4: 2 
5: 2 
6: 1 
7: 1 

因此,当您访问1时,您会在堆栈上推送367。您的父级设为1。这一切都很顺利。

您从堆栈中弹出7,您不会在堆栈上推送任何内容并且循环检查会清除,因此当您在循环中退出时,您将visited[7]设置为true并将您设为父7(!!!!!)。

您可以看到这样做不顺利,因为一旦您从堆栈中弹出6,您7就会保存为parent。它应该是1。这使得neighbor[0] != parent上的循环检查失败。

我建议在映射数组中添加parent,并通过应用union-merge来检测周期。