1. 程式人生 > >743. Network Delay Time(python+cpp)

743. Network Delay Time(python+cpp)

題目:

There are N network nodes, labelled 1 to N. Given times, a list of travel times as directed edges times[i] = (u, v, w), where u is the source node, v is the target node, and w is the time it takes for a signal to travel from source to target. Now, we send a signal from a certain node K. How long will it take for all nodes to receive the signal? If it is impossible, return -1

. Note: 1.N will be in the range [1, 100]. 2.K will be in the range [1, N]. The length of times will be in the range [1, 6000]. All edges times[i] = (u, v, w) will have 1 <= u, v <= N and 1 <= w <= 100.

解釋: 無向圖的最短路徑: Floyd演算法可以算出圖中所有節點之間的最短路徑長度 Dijkstra演算法只能求得某特定結點到其他所有結點的最短路徑長度 這道題目是有向圖,感覺可以用dfs做。 所有的結點都收到所需要的時間,就是每個結點都能收到的情況下,最遲收到訊號的結點收到訊號所需要的時間,如果有結點根本收不到訊號那麼就返回 解法參考《計算機考研機試指南的》p121 的Dijkstra演算法解法。 python程式碼:

#鄰接連結串列元素結構體
class E:
    def __init__(self,time,nxt):
        self.t=time
        self.next=nxt
class Solution(object):
    def networkDelayTime(self, times, N, K):
        """
        :type times: List[List[int]]
        :type N: int
        :type K: int
        :rtype: int
        """
        #鄰接連結串列,如果內層不是數字的話,不要輕易寫成乘法
edge=[[] for _ in range(N+1)] #距離向量,當mark[i]為True時,表示已經得到的最短路徑長度,否則表示所有從結點K出發,經過已知的最短路徑到達 #集合S中的某一點,再經過一條邊到達結點i的最短距離 Dis=[-1]*(N+1) Dis[0]=0 #是否屬於集合S,S陣列儲存當前最短路徑的集合 mark=[False]*(N+1) for time in times: a,b,c=time tmp1=E(c,b) edge[a].append(tmp1) # tmp2=E(c,a) # edge[b].append(tmp2) #起點為K Dis[K]=0 mark[K]=True newP=K #迴圈n-1次,尋找其他n-1個結點的最短路徑 for i in range(1,N): #遍歷與新加入的結點直接相連的邊 for j in range(len(edge[newP])): #該邊的另一個結點 tmpnext=edge[newP][j].next tmpt=edge[newP][j].t #若另一個結點也屬於集合S,則跳過 if mark[tmpnext]==True: continue #若該點尚不可達到或者該點從新加入的結點經過一條邊到達時比以往距離更短 if Dis[tmpnext]==-1 or Dis[tmpnext]>Dis[newP]+tmpt: Dis[tmpnext]=Dis[newP]+tmpt #K經過已知的最短路徑到達集合S中的某一點,再經過一條邊到達結點i的最短距離 _min=float('inf') #遍歷所有結點 for j in range(1,N+1): #若其屬於集合S,則跳過 if mark[j]==True: continue #若該結點還尚未到達 if Dis[j]==-1: continue if Dis[j]<_min: _min=Dis[j] newP=j#新加入的點暫定為該點 #加入到集合S中 mark[newP]=True return -1 if -1 in Dis else max(Dis)

c++程式碼:

//鄰接連結串列中的連結串列元素結構體
struct E
{
    int next;//代表直接相鄰的結點,注意這裡next不是指標
    int t;//代表改邊的權重
};
class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
        //鄰接連結串列
        vector<vector<E>>edge(N+1,vector<E>());
        //設已經確定了最短路徑長度的結點所構成的集合為集合S
        //標記,當mark[i]為true時,表示已經得到K到i的最短路徑長度
        vector<bool>mark(N+1,false);
        //距離向量,mark[i]為true時,表示K到i的最短路徑,否則表示從結點K出發到集合S中的某一點,再經過該點和i的連線到達i的距離
        vector<int>Dis(N+1,-1);
        //0結點不存在但是不能保持-1的值影響最終的結果
        Dis[0]=0;
        //構建鄰接表
        for(auto time:times)
        {
            int a=time[0],b=time[1],c=time[2];
            E tmp;
            tmp.next=b;
            tmp.t=c;
            edge[a].push_back(tmp);//由於是有向圖,所以這裡只需要寫一個
        }
        //起點為K
        Dis[K]=0;
        mark[K]=true;
        //集合S中新加入的結點為K
        int newP=K;
        //求其他N-1個結點的最短路徑長度
        for (int i=1;i<N+1;i++)
        {   
            //遍歷與新加入的結點newP相鄰的所有結點
            for(int j=0;j<edge[newP].size();j++)
            {
                int tmpnext=edge[newP][j].next;//該邊的另一個結點
                int tmpt=edge[newP][j].t;//該邊的權重
                //如果該結點已經在集合S中,表示已經求得K到tmpnext的最短路徑
                if(mark[tmpnext]==true)
                    continue;
                //若該結點尚不可達或者通過newP可以使得到達該結點的路徑更短
                if(Dis[tmpnext]==-1 || Dis[tmpnext]>Dis[newP]+tmpt)
                {
                    Dis[tmpnext]=Dis[newP]+tmpt;
                } 
                
            }
            //接下來要找一個新的結點加入集合S,也就是要找一個到K的距離最短的結點加入到S
            int _min=INT_MAX;
            //遍歷所有結點
            for(int j=1;j<N+1;j++)
            {
                //如果結點已經在S中,則跳過
                if(mark[j]==true)
                    continue;
                //如果該點仍不可到達,也跳過
                if(Dis[j]==-1)
                    continue;
                if (Dis[j]<_min)
                {
                    _min=Dis[j];
                    newP=j;//姑且先讓該點成為新加入的結點,反正後面還要更新。
                }
            }
            //把newP加入集合S
            mark[newP]=true;
            
        }
        if (count(Dis.begin(),Dis.end(),-1)!=0)
            return -1;
        else
            return *max_element(Dis.begin(),Dis.end());
    }
};

總結: