【Sicily】1007. 小黄车

题目描述

随着共享经济的兴起,大学城如今到处可见ofo小黄车. 小左现在打算每天都骑小黄车从宿舍去实验室. 假设大学城的地图可以简化为一个有向图,图中有N个地点(节点),用0到N-1进行编号,有些地点之间存在有向的道路(有向边). 小左的宿舍所在地点编号为0,实验室所在地点编号为N-1. 小左希望为连续的M天规划线路,使得每天从宿舍到实验室,都至少会经过一条之前没有走过的道路(有向边). 小左想知道M的最大值,你能帮助他么?

请实现下面Solution类中的countPath函数,完成上述功能.
参数G: N*N(2 <= N <= 50)邻接矩阵,如果地点i到地点j之间有道路,则G[i][j] = 1;否则G[i][j] = 0. G[i][i]的值总是为0.
返回值:M的最大值. 如果不存在满足要求的路径则返回0.

class Solution {
public:
       int countPaths(vector<vector<int>> G) {

};

例1:
G = {{0, 1}, {1, 0}},返回值为2,因为第1天:0 –> 1,第2天 0 –> 1 –> 0 –> 1. 虽然小左第2天兜了一下圈,但他确实走了一条第1天没有走过的边1 –> 0.

例2:
G = {{0, 1, 1}, {1, 0, 1}, {1, 0, 0}},返回值为4.
第1天:0 –> 2
第2天:0 –> 2 –> 0 –> 2
第3天:0 –> 1 –> 2
第4天:0 –> 1 –> 0 –> 1 –> 2

例3:
G = {{0, 1, 0}, {1, 0, 0}, {0, 0, 0}},返回值为0.

注意:
1. 你只需要提交Solution类的代码,你在本地可以编写main函数测试程序,但不需要提交main函数的代码.
2. 本题用近200组数据进行测试.

解题思路

图论
首先,去除起点访问不到的节点以及无法达到终点的节点。因为题目是要找到一条从起点到终点的增广路径,这些无法遍历到的节点及其对应的出边,入边,一定不会有贡献。
假设按上述要求去除节点之后,剩下k个节点和m条边。每经过一个节点,就需要消耗两条边(出边和入边),起点和终点除外,即m-2个节点。所以,可以得到,为了使每次遍历都至少有一条边是第一次访问的,最多的遍历次数是k - (m - 2)
更多详细描述,请参考这里.

AC代码

// Problem#: 20623
// Submission#: 5149517
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
class Solution {
public:
    int countPaths(vector<vector<int> > G) {
        int n = G.size();
        if (n < 2 || n > 50) return 0;

        vector<bool> canVisit(n, false);
        vector<bool> toDest(n, false);

        queue<int> q;
        // bfs to find all nodes that can be reached, starting from source
        q.push(0);
        while (!q.empty()) {
            int cur = q.front();
            q.pop();
            canVisit[cur] = true;
            for (int i = 0; i < n; ++i) {
                if (G[cur][i] && !canVisit[i]) 
                    q.push(i);
            }
        }
        // return 0 if the destination cannot be reached
        if (!canVisit[n - 1]) return 0;

        // bfs to find all nodes that cannot reach the sink
        q.push(n - 1);
        while (!q.empty()) {
            int cur = q.front();
            q.pop();
            toDest[cur] = true;
            for (int i = 0; i < n; ++i) {
                if (G[i][cur] && !toDest[i])
                    q.push(i);
            }
        }

        // find the remaining k edges and m nodes, M = k - (m - 2)
        int result = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (G[i][j] && canVisit[i] && canVisit[j] && toDest[i] && toDest[j])
                    result++;
            }
        }
        for (int i = 0; i < n; ++i) {
            if (canVisit[i] && toDest[i])
                result--;
        }
        return result + 2;    
    }      
};                                 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值