日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

ACM北大暑期课培训第六天

發(fā)布時(shí)間:2024/4/17 编程问答 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ACM北大暑期课培训第六天 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  今天講了DFA,最小生成樹(shù)以及最短路

?

  DFA(接著昨天講)

  如何高效的構(gòu)造前綴指針

  步驟為:根據(jù)深度一一求出每一個(gè)節(jié)點(diǎn)的前綴指針。對(duì)于當(dāng)前節(jié)點(diǎn),設(shè)他的父節(jié)點(diǎn)與他的邊上的字符為Ch,如果他的父節(jié)點(diǎn)的前綴指針?biāo)赶虻墓?jié)點(diǎn)的兒子中,有通過(guò)Ch字符指向的兒子,那么當(dāng)前節(jié)點(diǎn)的前綴指針指向該兒子節(jié)點(diǎn),否則通過(guò)當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)的前綴指針?biāo)赶螯c(diǎn)的前綴指針,繼續(xù)向上查找,直到到達(dá)根節(jié)點(diǎn)為止。

  ps:構(gòu)造前綴指針時(shí)在最前面加一個(gè)0號(hào)節(jié)點(diǎn)。

?

  對(duì)于一個(gè)插入了n個(gè)模式串的單詞 前綴樹(shù)構(gòu)造其前綴指針的時(shí)間復(fù)雜 度為:O(∑len(i)) (i=1..n)

?

  如何在建立好的Trie圖上遍歷

  遍歷的方法如下:從ROOT出發(fā),按照當(dāng)前串的下一 個(gè)字符ch來(lái)進(jìn)行在樹(shù)上的移動(dòng)。若當(dāng)前點(diǎn)P不存在通過(guò)ch連接的兒子,那么考慮P的前綴指針指向的節(jié)點(diǎn)Q,如果還無(wú)法找到通過(guò)ch連接的兒子節(jié)點(diǎn),再考慮Q的前綴指針… 直到找到通過(guò)ch連接的兒子,再繼續(xù)遍歷。如果遍歷過(guò)程中經(jīng)過(guò)了某個(gè)終止節(jié)點(diǎn),則說(shuō)明S包含該終止節(jié)點(diǎn)代表的模式串. 如果遍歷過(guò)程中經(jīng)過(guò)了某個(gè)非終止節(jié)點(diǎn)的危險(xiǎn)節(jié)點(diǎn), 則可以斷定S包含某個(gè)模式串。要找出是哪個(gè),沿著危險(xiǎn)節(jié)點(diǎn)的前綴指針鏈走,碰到終止節(jié)點(diǎn)即可。

  ps:? ?危險(xiǎn)節(jié)點(diǎn):1) 終止節(jié)點(diǎn)是危險(xiǎn)節(jié)點(diǎn)? ? ? ? 2) 如果一個(gè)節(jié)點(diǎn)的前綴指針指向危險(xiǎn)節(jié)點(diǎn),那么它也是危險(xiǎn)節(jié)點(diǎn)。

    這樣遍歷一個(gè)串S的時(shí)間復(fù)雜度是O(len(S))

?

  最純粹的Trie圖題目:

給N個(gè)模式串,每個(gè)不超過(guò)個(gè)字符,再給M個(gè)句子,句子長(zhǎng)度< 100 判斷每個(gè)句子里是否包含模式串 N < 10, M < 10 ,字符都是小寫(xiě)字母 5 8 abcde defg cdke ab f abcdkef abkef bcd bca add ab qab f 題目 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <queue> 6 using namespace std; 7 #define LETTERS 26 8 int nNodesCount = 0; 9 struct CNode 10 { 11 CNode * pChilds[LETTERS]; 12 CNode * pPrev; //前綴指針 13 bool bBadNode; //是否是危險(xiǎn)節(jié)點(diǎn) 14 void Init() 15 { 16 memset(pChilds,0,sizeof(pChilds)); 17 bBadNode = false; 18 pPrev = NULL; 19 } 20 }; 21 CNode Tree[200]; //10個(gè)模式串,每個(gè)10個(gè)字符,每個(gè)字符一個(gè)節(jié)點(diǎn),也只要100個(gè)節(jié)點(diǎn) 22 23 void Insert( CNode * pRoot, char * s) 24 { 25 //將模式串s插入trie樹(shù) 26 for( int i = 0; s[i]; i ++ ) 27 { 28 if( pRoot->pChilds[s[i]-'a'] == NULL) 29 { 30 pRoot->pChilds[s[i]-'a'] =Tree + nNodesCount; 31 nNodesCount ++; 32 } 33 pRoot = pRoot->pChilds[s[i]-'a']; 34 } 35 pRoot-> bBadNode = true; 36 } 37 void BuildDfa( ) 38 { 39 //在trie樹(shù)上加前綴指針 40 for( int i = 0; i < LETTERS ; i ++ ) 41 Tree[0].pChilds[i] = Tree + 1; 42 Tree[0].pPrev = NULL; 43 Tree[1].pPrev = Tree; 44 deque<CNode * > q; 45 q.push_back(Tree+1); 46 while( ! q.empty() ) 47 { 48 CNode * pRoot = q.front(); 49 q.pop_front(); 50 for( int i = 0; i < LETTERS ; i ++ ) 51 { 52 CNode * p = pRoot->pChilds[i]; 53 if( p) 54 { 55 CNode * pPrev = pRoot->pPrev; 56 while( pPrev ) 57 { 58 if( pPrev->pChilds[i] ) 59 { 60 p->pPrev = pPrev->pChilds[i]; 61 if( p->pPrev-> bBadNode) 62 p-> bBadNode = true; 63 //自己的pPrev指向的節(jié)點(diǎn)是危險(xiǎn)節(jié)點(diǎn),則自己也是危險(xiǎn)節(jié)點(diǎn) 64 break; 65 } 66 else 67 pPrev = pPrev->pPrev; 68 } 69 q.push_back(p); 70 } 71 } 72 } //對(duì)應(yīng)于while( ! q.empty() ) 73 } 74 bool SearchDfa(char * s) 75 { 76 //返回值為true則說(shuō)明包含模式串 77 CNode * p = Tree + 1; 78 for( int i = 0; s[i] ; i ++ ) 79 { 80 while(true) 81 { 82 if( p->pChilds[s[i]-'a']) 83 { 84 p = p->pChilds[s[i]-'a']; 85 if( p-> bBadNode) 86 return true; 87 break; 88 } 89 else 90 p = p->pPrev; 91 } 92 } 93 return false; 94 } 95 int main() 96 { 97 nNodesCount = 2; 98 int M,N; 99 scanf("%d%d",&N,&M); //N個(gè)模式串,M個(gè)句子 100 for( int i = 0; i < N; i ++ ) 101 { 102 char s[20]; 103 scanf("%s",s); 104 Insert(Tree + 1,s); 105 } 106 BuildDfa(); 107 for( int i = 0 ; i < M; i ++ ) 108 { 109 char s[200]; 110 scanf("%s",s); 111 cout << SearchDfa(s) << endl; 112 } 113 return 0; 114 } 代碼

?

PS:有可能模式串A是另一模式串B的子串,此情況下可能只能得出匹配B的結(jié)論而忽略也匹配A,所以不能只看終止節(jié)點(diǎn),還要看危險(xiǎn)節(jié)點(diǎn):

   對(duì)每個(gè)節(jié)點(diǎn)設(shè)置一個(gè)“是否計(jì)算過(guò)”的標(biāo)記,當(dāng)標(biāo)記一個(gè)危險(xiǎn)節(jié)點(diǎn)為“已匹配”時(shí),沿該節(jié)點(diǎn)對(duì)應(yīng)的S的所有后綴指針一直到根節(jié)點(diǎn)全標(biāo)記為“已匹配”。

?

例題:1.POJ3987?Computer Virus on Planet Pandora?2010 福州賽區(qū)題目

   2.POI #7 題:病毒

   3.POJ 3691 DNA repair

   4.POJ 1625?Censored!

   5.POJ2778 DNA Sequence

?

  最小生成樹(shù)(MST)問(wèn)題

  ?生成樹(shù):

  1.無(wú)向連通圖的邊的集合

  2.無(wú)回路

  3.連接所有的點(diǎn)

  最小:? ? ? ? ?所有邊的權(quán)值之和最小

  有n個(gè)頂點(diǎn),n-1條邊

?

  Prim算法

  假設(shè)G=(V,E)是一個(gè)具有n個(gè)頂點(diǎn)的連通網(wǎng), T=(U,TE)是G的最小生成樹(shù),U,TE初值均為空集。

  首先從V中任取一個(gè)頂點(diǎn)(假定取v1),將它并入U(xiǎn)中,此時(shí)U={v1},然后只要U是V的真子集(U∈V), 就從那些一個(gè)端點(diǎn)已在T中,另一個(gè)端點(diǎn)仍在T外 的所有邊中,找一條最短邊,設(shè)為(vi ,vj ),其中 vi∈U,vj∈V-U,并把該邊(vi , vj )和頂點(diǎn)vj分別并入T 的邊集TE和頂點(diǎn)集U,如此進(jìn)行下去,每次往生成樹(shù)里并入一個(gè)頂點(diǎn)和一條邊,直到n-1次后得到最小生成樹(shù)。

  關(guān)鍵問(wèn)題:每次如何從連接T中和T外頂點(diǎn)的所有邊中,找 到一條最短的

    1) 如果用鄰接矩陣存放圖,而且選取最短邊的時(shí)候遍歷所有點(diǎn)進(jìn)行選取,則總時(shí)間復(fù)雜度為 O(V2 ), V為頂點(diǎn)個(gè)數(shù)

    2)用鄰接表存放圖,并使用堆來(lái)選取最短邊,則總時(shí)間復(fù)雜度為O(ElogV)

    不加堆優(yōu)化的Prim 算法適用于密集圖,加堆優(yōu)化的適用于稀疏圖

?

  Kruskal算法

  假設(shè)G=(V,E)是一個(gè)具有n個(gè)頂點(diǎn)的連通網(wǎng), T=(U,TE)是G的最小生成樹(shù),U=V,TE初值為 空。

  將圖G中的邊按權(quán)值從小到大依次選取,若選取的邊使生成樹(shù)不形成回路,則把它并入TE中,若形成回路則將其舍棄,直到TE 中包含N-1條邊為止,此時(shí)T為最小生成樹(shù)。

  關(guān)鍵問(wèn)題:如何判斷欲加入的一條邊是否與生成樹(shù) 中邊構(gòu)成回路。

    利用并查集

?

  Kruskal 和 Prim 比較

  Kruskal:將所有邊從小到大加入,在此過(guò)程中 判斷是否構(gòu)成回路

    – 使用數(shù)據(jù)結(jié)構(gòu):并查集

    – 時(shí)間復(fù)雜度:O(ElogE)

     – 適用于稀疏圖

  Prim:從任一節(jié)點(diǎn)出發(fā),不斷擴(kuò)展

    – 使用數(shù)據(jù)結(jié)構(gòu):堆

    – 時(shí)間復(fù)雜度:O(ElogV) 或 O(VlogV+E)(斐波那契堆)

    – 適用于密集圖

    – 若不用堆則時(shí)間復(fù)雜度為O(V2)

?

?

例題:1.POJ 1258?Agri-Net

   2.POJ 2349?Arctic Network

   3. 2011 ACM/ICPC亞洲區(qū)預(yù)選賽北京賽站

    Problem A. Qin Shi Huang’s National Road System

?

  最短路算法

  Dijkstra 算法? ?解決無(wú)負(fù)權(quán)邊的帶權(quán)有向圖 或 無(wú)向圖的單源最短路問(wèn)題

?

  用鄰接表,不優(yōu)化,時(shí)間復(fù)雜度O(V2+E)

  Dijkstra+堆的時(shí)間復(fù)雜度 o(ElgV)

  用斐波那契堆可以做到O(VlogV+E)

  若要輸出路徑,則設(shè)置prev數(shù)組記錄每個(gè)節(jié)點(diǎn)的前趨點(diǎn),在d[i] 更新時(shí)更新prev[i]

?

  Dijkstra算法實(shí)現(xiàn):

    已經(jīng)求出到V0點(diǎn)的最短路的點(diǎn)的集合為T(mén)?

    維護(hù)Dist數(shù)組,Dist[i]表示目前Vi到V0的“距離”

    開(kāi)始Dist[0] = 0, 其他Dist[i] = 無(wú)窮大, T為空集

   1) 若|T| = N,算法完成,Dist數(shù)組就是解。否則取Dist[i]最 小的不在T中的點(diǎn)Vi, 將其加入T,Dist[i]就是Vi到V0的最短 路長(zhǎng)度。

   2) 更新所有與Vi有邊相連且不在T中的點(diǎn)Vj的Dist值:? Dist[j] = min(Dist[j],Dist[i]+W(Vi,Vj))?

   3) 轉(zhuǎn)到1)

?

例題:1.POJ 3159 Candies

?

  Bellman-Ford算法

  解決含負(fù)權(quán)邊的帶權(quán)有向圖的單源最短路徑問(wèn)題?

  不能處理帶負(fù)權(quán)邊的無(wú)向圖(因可以來(lái)回走一條負(fù)權(quán)邊)

  限制條件: 要求圖中不能包含權(quán)值總和為負(fù)值回路(負(fù)權(quán)值回路),如下圖所示。?

?

?  Bellman-Ford算法思想:

    構(gòu)造一個(gè)最短路徑長(zhǎng)度數(shù)組序列dist 1 [u], dist 2 [u], …, dist n-1 [u] (u = 0,1…n-1,n為點(diǎn)數(shù))

    dist n-1 [u]為從源點(diǎn)v出發(fā)最多經(jīng)過(guò)不構(gòu)成負(fù)權(quán)值回路n-1條邊到達(dá)終點(diǎn)u的 最短路徑長(zhǎng)度;

?    算法的最終目的是計(jì)算出dist n-1 [u],為源點(diǎn)v到頂點(diǎn)u的最短路徑長(zhǎng)度。

?    遞推公式(求頂點(diǎn)u到源點(diǎn)v的最短路徑):

      dist 1 [u] = Edge[v][u]

      dist k [u] = min{ dist k-1 [u], min{ dist k-1 [j] + Edge[j][u] } }, j=0,1,…,n-1,j≠u

?

  若存在dist?n?[u]? < dist n-1?[u],則說(shuō)明存在從源點(diǎn)可達(dá)的負(fù)權(quán)值回路

   在求出distn-1[ ]之后,再對(duì)每條邊<u,k>判斷一下:加入這條邊是否會(huì)使得頂點(diǎn)k的最短路徑值再縮短,即判斷:dist[u]+w(u,k)<dist[k]否成立,如果成立,則說(shuō)明存在從源點(diǎn)可達(dá)的負(fù)權(quán)值回路。

  存在負(fù)權(quán)回路就一定能導(dǎo)致該式成立的證明:

  如果成立,則說(shuō)明找到了一條經(jīng)過(guò)了n條邊的從 s 到k的路徑,且 其比任何少于n條邊的從s到k的路徑都短。

  一共n個(gè)頂點(diǎn),路徑卻經(jīng)過(guò)了n條邊,則必有一個(gè)頂點(diǎn)m經(jīng)過(guò)了至少 兩次。則m是一個(gè)回路的起點(diǎn)和終點(diǎn)。走這個(gè)回路比不走這個(gè)回路 路徑更短,只能說(shuō)明這個(gè)回路是負(fù)權(quán)回路。

  

  Bellman-Ford算法改進(jìn):

  Bellman-Ford算法不一定要循環(huán)n-1次,n為頂點(diǎn)個(gè)數(shù),只要在某次循環(huán)過(guò)程中,考慮每條邊后,源點(diǎn)到所有頂點(diǎn)的最短路徑 長(zhǎng)度都沒(méi)有變,那么Bellman-Ford算法就可以提前結(jié)束了

?

  Dijkstra算法與Bellman-Ford算法的區(qū)別?

  Dijkstra算法和Bellman算法思想有很大的區(qū)別:

    Dijkstra算法在求解過(guò)程中,源點(diǎn)到集合S內(nèi)各頂點(diǎn)的最短路徑一旦求出,則之后不變了,修改的僅僅是源點(diǎn)到S外各頂點(diǎn)的最短路徑長(zhǎng)度。

    Bellman-Ford算法在求解過(guò)程中,每次循環(huán)都要修改所有頂點(diǎn)的dist[ ],也就是說(shuō)源點(diǎn)到各頂點(diǎn)最短路徑長(zhǎng)度一 直要到算法結(jié)束才確定下來(lái)。

?

?

例題:1.POJ 3259 Wormholes

要求判斷任意兩點(diǎn)都能僅通過(guò)正邊就互相可達(dá)的有向圖(圖中有 重邊)中是否存在負(fù)權(quán)環(huán) Sample Input 2 3 3 1 1 2 2 1 3 4 2 3 1 3 1 3 3 2 1 1 2 3 2 3 4 3 1 8Sample Output NO YES2個(gè)test case 每個(gè)test case 第一行: N M W (N<=500,M<=2500,W<=200) N個(gè)點(diǎn) M條雙向正權(quán)邊 W條單向負(fù)權(quán)邊 第一個(gè)test case 最后一行 3 1 3 是單向負(fù)權(quán)邊,3->1的邊權(quán)值是-3 題目 1 //by guo wei 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 int F,N,M,W; 6 const int INF = 1 << 30; 7 struct Edge 8 { 9 int s,e,w; 10 Edge(int ss,int ee,int ww):s(ss),e(ee),w(ww) { } 11 Edge() { } 12 }; 13 vector<Edge> edges; //所有的邊 14 int dist[1000]; 15 int Bellman_ford(int v) 16 { 17 for( int i = 1; i <= N; ++i) 18 dist[i] = INF; 19 dist[v] = 0; 20 for( int k = 1; k < N; ++k) //經(jīng)過(guò)不超過(guò)k條邊 21 { 22 for( int i = 0; i < edges.size(); ++i) 23 { 24 int s = edges[i].s; 25 int e = edges[i].e; 26 if( dist[s] + edges[i].w < dist[e]) 27 dist[e] = dist[s] + edges[i].w; 28 } 29 } 30 for( int i = 0; i < edges.size(); ++ i) 31 { 32 int s = edges[i].s; 33 int e = edges[i].e; 34 if( dist[s] + edges[i].w < dist[e]) 35 return true; 36 } 37 return false; 38 } 39 int main() 40 { 41 cin >> F; 42 while( F--) 43 { 44 edges.clear(); 45 cin >> N >> M >> W; 46 for( int i = 0; i < M; ++ i) 47 { 48 int s,e,t; 49 cin >> s >> e >> t; 50 edges.push_back(Edge(s,e,t)); //雙向邊等于兩條邊 51 edges.push_back(Edge(e,s,t)); 52 } 53 for( int i = 0; i < W; ++i) 54 { 55 int s,e,t; 56 cin >> s >> e >> t; 57 edges.push_back(Edge(s,e,-t)); 58 } 59 if( Bellman_ford(1))//從1可達(dá)所有點(diǎn) 60 cout << "YES" <<endl; 61 else cout << "NO" <<endl; 62 } 63 } View Code for( int k = 1; k < N; ++k) { //經(jīng)過(guò)不超過(guò)k條邊for( int i = 0;i < edges.size(); ++i) {int s = edges[i].s;int e = edges[i].e;if( dist[s] + edges[i].w < dist[e])dist[e] = dist[s] + edges[i].w; } }會(huì)導(dǎo)致在一次內(nèi)層循環(huán)中,更新了某個(gè) dist[x]后,以后又用dist[x]去更新dist[y],這樣dist[y]就是經(jīng)過(guò)最多不超過(guò)k+1條邊的情況了出現(xiàn)這種情況沒(méi)有關(guān)系,因?yàn)檎麄€(gè) for( int k = 1; k < N; ++k) 循環(huán)的目的是要確保,對(duì)任意點(diǎn)u,如果從源s到u的最短路是經(jīng)過(guò)不超過(guò)n-1條邊的,則這條最短路不會(huì)被忽略。至于計(jì)算過(guò)程中對(duì)某些點(diǎn) v 計(jì)算出了從s->v的經(jīng)過(guò)超過(guò)N-1條邊的最短路的情況,也不影響結(jié)果正確性。若是從s->v的經(jīng)過(guò)超過(guò)N-1條邊的結(jié)果比經(jīng)過(guò)最多N-1條邊的結(jié)果更小,那一定就有負(fù)權(quán)回路。有負(fù)權(quán)回路的情況下,再多做任意多次循環(huán),每次都會(huì)發(fā)現(xiàn)到有些點(diǎn)的最短路變得更短了。 問(wèn)題

   2.POJ 1860

   3.POJ 3259

   4.POJ 2240

?

?  SPFA算法

?  快速求解含負(fù)權(quán)邊的帶權(quán)有向圖的單源最短路徑問(wèn)題

  是Bellman-Ford算法的改進(jìn)版,利用隊(duì)列動(dòng)態(tài)更新dist[]

?

  維護(hù)一個(gè)隊(duì)列,里面存放所有需要進(jìn)行迭代的點(diǎn)。初始時(shí)隊(duì)列中只有一個(gè) 源點(diǎn)S。用一個(gè)布爾數(shù)組記錄每個(gè)點(diǎn)是否處在隊(duì)列中。

  每次迭代,取出隊(duì)頭的點(diǎn)v,依次枚舉從v出發(fā)的邊v->u,若 Dist[v]+len(v->u) 小于Dist[u],則改進(jìn)Dist[u](可同時(shí)將u前驅(qū)記為v)。 此時(shí)由于S到u的最短距離變小了,有可能u可以改進(jìn)其它的點(diǎn),所以若u不在隊(duì)列中,就將它放入隊(duì)尾。這樣一直迭代下去直到隊(duì)列變空,也就是S到所有節(jié)點(diǎn)的最短距離都確定下來(lái),結(jié)束算法。若一個(gè)點(diǎn)最短路被改進(jìn)的次數(shù)達(dá)到n ,則有負(fù)權(quán)環(huán)(原因同B-F算法。可以用spfa算法判斷圖有無(wú)負(fù)權(quán)環(huán)

  在平均情況下,SPFA算法的期望時(shí)間復(fù)雜度為O(E)。

?

?例題:1.POJ 3259 Wormholes

要求判斷任意兩點(diǎn)都能僅通過(guò)正邊就互相可達(dá)的有向圖(圖中有 重邊)中是否存在負(fù)權(quán)環(huán) Sample Input 2 3 3 1 1 2 2 1 3 4 2 3 1 3 1 3 3 2 1 1 2 3 2 3 4 3 1 8Sample Output NO YES2個(gè)test case 每個(gè)test case 第一行: N M W (N<=500,M<=2500,W<=200) N個(gè)點(diǎn) M條雙向正權(quán)邊 W條單向負(fù)權(quán)邊 第一個(gè)test case 最后一行 3 1 3 是單向負(fù)權(quán)邊,3->1的邊權(quán)值是-3 題目 1 ///POJ3259 Wormholes 判斷有沒(méi)有負(fù)權(quán)環(huán)spfa 2 //by guo wei 3 #include <iostream> 4 #include <vector> 5 #include <queue> 6 #include <cstring> 7 using namespace std; 8 int F,N,M,W; 9 const int INF = 1 << 30; 10 struct Edge 11 { 12 int e,w; 13 Edge(int ee,int ww):e(ee),w(ww) { } 14 Edge() { } 15 }; 16 vector<Edge> G[1000]; //整個(gè)有向圖 17 int updateTimes[1000]; //最短路的改進(jìn)次數(shù) 18 int dist[1000]; //dist[i]是源到i的目前最短路長(zhǎng)度 19 int Spfa(int v) 20 { 21 for( int i = 1; i <= N; ++i) 22 dist[i] = INF; 23 dist[v] = 0; 24 queue<int> que; 25 que.push(v); 26 memset(updateTimes,0,sizeof(updateTimes)); 27 while( !que.empty()) 28 { 29 int s = que.front(); 30 que.pop(); 31 for( int i = 0; i < G[s].size(); ++i) 32 { 33 int e = G[s][i].e; 34 if( dist[e] > dist[s] + G[s][i].w ) 35 { 36 dist[e] = dist[s] + G[s][i].w; 37 que.push(e); //沒(méi)判隊(duì)列里是否已經(jīng)有e,可能會(huì)慢一些 38 ++updateTimes[e]; 39 if( updateTimes[e] >= N) return true; 40 } 41 } 42 } 43 return false; 44 } 45 int main() 46 { 47 cin >> F; 48 while( F--) 49 { 50 cin >> N >> M >> W; 51 for( int i = 1; i <1000; ++i) 52 G[i].clear(); 53 int s,e,t; 54 for( int i = 0; i < M; ++ i) 55 { 56 cin >> s >> e >> t; 57 G[s].push_back(Edge(e,t)); 58 G[e].push_back(Edge(s,t)); 59 } 60 for( int i = 0; i < W; ++i) 61 { 62 cin >> s >> e >> t; 63 G[s].push_back(Edge(e,-t)); 64 } 65 if( Spfa(1)) 66 cout << "YES" <<endl; 67 else cout << "NO" <<endl; 68 } 69 } POJ 3259

    2.POJ 2387

    3.POJ 3256

?

  弗洛伊德算法

  用于求每一對(duì)頂點(diǎn)之間的最短路徑。有向圖,無(wú)向圖均可,也可以有負(fù)權(quán)邊。但不適合于有負(fù)權(quán)回路的題

  復(fù)雜度O(n3)

///弗洛伊德算法偽代碼(三層循環(huán)) for( int i = 1 ; i <= vtxnum; ++i )for( int j = 1; j <= vtxnum; ++j){dist[i][j] = cost[i][j]; // cost是邊權(quán)值, dist是兩點(diǎn)間最短距離if( dist[i][j] < INFINITE) //i到j(luò)有邊path[i,j] = [i]+[j]; //path是路徑 } for( k = 1; k <= vtxnum; ++k) //每次求中間點(diǎn)標(biāo)號(hào)不超過(guò)k的i到j(luò)最短路for( int i = 1; i <= vtxnum; ++i)for(int j = 1; j <= vtxnum ; ++j)if( dist[i][k] + dist[k][j] < dist[i][j]){dist[i][j] = dist[i][k]+dist[k][j];path[i,j] = path[i,k]+path[k,j];}

?

例題:1.POJ 3660 Cow Contest

   2.POJ 1125

?

轉(zhuǎn)載于:https://www.cnblogs.com/l999q/p/9393372.html

總結(jié)

以上是生活随笔為你收集整理的ACM北大暑期课培训第六天的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。