多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 圖算法小結(prime與dijkstra對比)

圖算法小結(prime與dijkstra對比)

來源:程序員人生   發布時間:2015-04-20 08:26:31 閱讀次數:3861次

(0)Dijstra 最短路徑和prim最小生成樹算法,神似,只是在更新dist時的if條件不同;主要是這類prime 的計算兩個集合間的最小值的思想非常重要。

(1)某省自從實行了很多年的暢通工程計劃后,終究修建了很多路。不過路多了也不好,每次要從1個城鎮到另外一個城鎮時,都有許多種道路方案可以選擇,而某些方案要比另外一些方案行走的距離要短很多。這讓行人很困擾。
現在,已知出發點和終點,請你計算出要從出發點到終點,最短需要行走多少距離。
Input
本題目包括多組數據,請處理到文件結束。
每組數據第1行包括兩個正整數N和M(0<N<200,0<M<1000),分別代表現有城鎮的數目和已修建的道路的數目。城鎮分別以0~N⑴編號。
接下來是M行道路信息。每行有3個整數A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城鎮A和城鎮B之間有1條長度為X的雙向道路。
再接下1行有兩個整數S,T(0<=S,T<N),分別代表出發點和終點。
Output
對每組數據,請在1行里輸出最短需要行走的距離。如果不存在從S到T的線路,就輸出⑴.

Sample Input
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2

Sample Output
2

// prime 和 dij算法的核心 ―― 如何保證當前的最小邊是終究的最小邊, // 上面試最小生成樹的算法,下面是最短路徑的算法了 #include <iostream> #include <cstring> using namespace std; const int INF = 1000000; const int MAX_SIZE = 200; int map[MAX_SIZE][MAX_SIZE]; bool visited[MAX_SIZE]; int disit[MAX_SIZE]; //存儲距離 //s開始位置,e結束位置 void dij_method(int s, int e, int N) { // init the params of dij memset(visited, false, sizeof(visited)); for (int i = 0; i < N; i++) { if (map[s][i] == ⑴) disit[i] = INF; else disit[i] = map[s][i]; } // 從s 點開始計算 visited[s] = true; for (int i = 1; i < N; i++) { int min = INF; int index = 0; // 找當前最小的 (這與prime1樣,只是if條件更強了) for (int j = 0; j < N; j++) { if (!visited[j] && j != s && disit[j] != ⑴ && disit[j] < min) { min = disit[j]; index = j; } } visited[index] = true;//頂點并入U集 if (index == e) //如果已到達終點 break; // 調劑更新目前的最短距離(這與這與prime1樣,只是if條件不1樣而已) for (int j = 0; j < N; j++) { if (!visited[j] && map[index][j] != ⑴ && (min + map[index][j]) < disit[j]) { disit[j] = min + map[index][j]; } }// end of for }// end of for } int main() { int N, M;// 點數和記錄數 int ori, des, len;// int start, end; while (cin >> N >> M) { memset(map, ⑴, sizeof(map)); //⑴表示不可達 while (M--) { cin >> ori >> end >> len; //有可能有更小的路徑 if (map[ori][des] == ⑴ || len < map[ori][des]) { map[ori][des] = len; map[des][ori] = len; } } // input and input start and end. cin >> start >> end; if (start == end) { cout << 0 << endl; continue; } // 調用無負權邊的圖(Dijkstra算法) dij_method(start, end, N); if (visited[end] && disit[end] < INF) cout << disit[end] << endl; else cout << ⑴ << endl; } return 0; }

(2)* About:    有向圖的Dijkstra算法實現
輸入數據:
5
7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60
輸出數據:
999999 10 999999 30 100
10 999999 50 999999 999999
999999 50 999999 20 10
30 999999 20 999999 60
100 999999 10 60 999999
源點到最后1個頂點的最短路徑長度: 60
源點到最后1個頂點的路徑為: 1 -> 4 -> 3 -> 5

#include <iostream> using namespace std; const int maxnum = 100; const int maxint = 999999; void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum]) { bool s[maxnum]; // 判斷是不是已存入該點到S集合中 for(int i=1; i<=n; ++i) { dist[i] = c[v][i]; s[i] = 0; // 初始都未用過該點 if(dist[i] == maxint) prev[i] = 0; else prev[i] = v; } dist[v] = 0; s[v] = 1; // 順次將未放入S集合的結點中,取dist[]最小值的結點,放入結合S中 // 1旦S包括了所有V中頂點,dist就記錄了從源點到所有其他頂點之間的最短路徑長度 for(int i=2; i<=n; ++i) { int tmp = maxint; int u = v; // 找出當前未使用的點j的dist[j]最小值 for(int j=1; j<=n; ++j) if((!s[j]) && dist[j]<tmp) { u = j; // u保存當前鄰接點中距離最小的點的號碼 tmp = dist[j]; } s[u] = 1; // 表示u點已存入S集合中 // 更新dist for(int j=1; j<=n; ++j) if((!s[j]) && c[u][j]<maxint) { int newdist = dist[u] + c[u][j]; if(newdist < dist[j]) { dist[j] = newdist; prev[j] = u; } } } } void searchPath(int *prev,int v, int u) { int que[maxnum]; int tot = 1; que[tot] = u; tot++; int tmp = prev[u]; while(tmp != v) { que[tot] = tmp; tot++; tmp = prev[tmp]; } que[tot] = v; for(int i=tot; i>=1; --i) if(i != 1) cout << que[i] << " -> "; else cout << que[i] << endl; } int main() { freopen("input.txt", "r", stdin); // 各數組都從下標1開始 int dist[maxnum]; // 表示當前點到源點的最短路徑長度 int prev[maxnum]; // 記錄當前點的前1個結點 int c[maxnum][maxnum]; // 記錄圖的兩點間路徑長度 int n, line; // 圖的結點數和路徑數 // 輸入結點數 cin >> n; // 輸入路徑數 cin >> line; int p, q, len; // 輸入p, q兩點及其路徑長度 // 初始化c[][]為maxint for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) c[i][j] = maxint; for(int i=1; i<=line; ++i) { cin >> p >> q >> len; if(len < c[p][q]) // 有重邊 { c[p][q] = len; // p指向q c[q][p] = len; // q指向p,這樣表示無向圖 } } for(int i=1; i<=n; ++i) dist[i] = maxint; for(int i=1; i<=n; ++i) { for(int j=1; j<=n; ++j) printf("%8d", c[i][j]); printf(" "); } Dijkstra(n, 1, dist, prev, c); // 最短路徑長度 cout << "源點到最后1個頂點的最短路徑長度: " << dist[n] << endl; // 路徑 cout << "源點到最后1個頂點的路徑為: "; searchPath(prev, 1, n); }

(3)

//poj2367題意: 知道1個數n, 然后n行,編號1到n, 每行輸入幾個數, //該行的編號排在這幾個數前面,輸出1種符合要求的編號名次排序。 #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int MAXN = 105; bool adj[MAXN][MAXN];// 林街邊 int in_degree[MAXN];// 入度 int result[MAXN];// 結果順序 void topo_sort(const int n) { int i,j,k; memset(in_degree,0,sizeof(in_degree)); for(i=1; i<=n; i++) //尋覓入度為零的節點 { for(j=1; j<=n; j++) { if(adj[i][j]) in_degree[j]++; } }// 可以在輸入的時候就計算入度的數值 for(i=1; i<=n; i++)// 這1個i表示個數的 { for(j=1; j<=n; j++) { if(in_degree[j]==0) { k=j; break; } } in_degree[k]=⑴;// 標志,已訪問過 result[i]=k; for(j=1; j<=n; j++) //入度減1 { if(adj[k][j]) { in_degree[j]--; } }// end of for }// end of for } int main() { int i,tem; int n; //init and input memset(adj,false,sizeof(adj)); scanf("%d",&n); for(i=1; i<=n; i++) { while(scanf("%dtem",&tem),tem) { adj[i][tem]=true; } } // topo_sort topo_sort(n); for(i=1; i<=n; i++) { if(i==1) printf("%d",result[i]); else printf(" %d",result[i]); } printf(" "); return 0; }
(4)

POJ 3249 拓撲排序+動態計劃
分類: ACM 2012-06⑴1 13:38 812人瀏覽 評論(0) 收藏 舉報
inputdelete存儲struct
該題是讓求在1個有向無環圖中,從1個入度為 0 的節點動身,到1個出度為 0 的節點的最大的權值問題。我們可使用廣搜,但是會超時,上網查了1下解題報告,可使用拓撲排序+動態計劃來解決此問題:
dp[1] = max{ dp[2] + cost[1] , dp[3] + cost[1] };
dp[2] = cost[2] + dp[4];
dp[3] = cost[3] + dp[4];
dp[4] = cost[4];
dp[5] = cost[5] + dp[6];
dp[6] = cost[6];
在拓撲排序的進程中,是入度為0的節點先入隊列,所以我們可以做1個逆置思考,是的 dp[i] 存儲的是入度為零的節點到當前節點的最大權值和,而最后在出度為 0 的節點的 dp[i] 中搜索最大的權值。代碼實現以下:

#include <iostream> #include <queue> #include <cstdio> using namespace std; #define N 100100 #define M 1000100 #define INF 1<<29 struct node { int v; int next; } edge[M]; int dp[N]; // 最大價值 存儲 由 拓撲排序后 入度為0的節點到當前節點最大的 profit int enext[N]; //記錄節點 i 當前的邊,由當前的邊 推出 下1條邊 int indegree[N]; //入度 int cost[N]; //價值 int res; int idx; std::queue<int > q; int m,n,a,b,i,j; void input() { for(i=1;i<=n;i++) { scanf("%d",&cost[i]); dp[i] = -INF; indegree[i] = 0; } idx=0; //memset(dp,-INF,sizeof(int)*(n+10) ); //memset(indegree,0,sizeof(int)*(n+10) ); //節點度數初始化為0 memset(enext,⑴,sizeof(enext) ); //說明當前節點只此1條邊 for(i=1;i<=m;i++) { scanf("%d %d",&a,&b); edge[idx].v = b; edge[idx].next = enext[a]; enext[a] = idx++; indegree[b]++; } while( !q.empty() ) q.pop(); for( i=1;i<=n;i++) if( !indegree[i] ) q.push(i),dp[i]=cost[i]; } int dag() { res = -INF; while( !q.empty() ) { int cur = q.front(); q.pop(); bool flag = true; //只有節點的出度為 0 的時候,我們才判斷其是不是有最大profit int nextid; // cout<<"cur : "<<cur<<endl; for( i=enext[cur] ; i != ⑴ ; i = edge[i].next) //遍歷當前頂點的所有的邊 { flag = false; nextid = edge[i].v ; // cout<<"nextid : "<<nextid<<endl; if( dp[nextid] < cost[ nextid ] + dp[cur]) dp[nextid] = cost[nextid] + dp[cur]; indegree[nextid]--; if( !indegree[nextid] ) { q.push(nextid); } } if( flag && dp[cur] > res ) res = dp[cur]; } return res; } int main() { while(scanf("%d %d",&n,&m) != EOF) { input(); printf("%d ",dag()); } return 0; }

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: www.99视频| yellow中文字幕在线 | 亚洲欧美日本韩国 | 国产在线精品一区二区不卡 | 99久久精品国内 | 亚洲欧美一级久久精品 | 国产亚洲欧美日韩在线看片 | 日本乱人伦片中文字幕三区 | 久久精品国产69国产精品亚洲 | 亚洲一区二区影院 | 成人在线视频国产 | 国产成人在线免费视频 | 国产第一页在线观看 | 天啦噜tianlalu精品视频 | 一区二区高清视频在线观看 | 成年人网站在线观看视频 | 波多野结衣视频一区二区 | 国产精品亚洲二区在线 | 精品国产日韩亚洲一区91 | 国产日产欧美精品 | 欧美国产亚洲精品高清不卡 | 99伊人| 在线观看免费xx高清视频 | 亚洲视频成人 | 久久精品国产一区二区 | 1024在线视频国产在线播放 | 日本护士xxxxx高清免费 | 在线视频 亚洲 | 武则天全黄肉体毛片免费看 | v视界成人影院在线视频 | 精品国产一区二区三区19 | 黄网站色网址 | 成人性色生活片免费看爆迷你毛片 | 国产欧美日韩另类va在线 | 国产精品国产亚洲精品看不卡 | 成人在线观看一区 | 波多野结衣在线不卡 | 欧美激情 亚洲 | 黄色中文字幕在线观看 | 亚洲一区二区三区精品国产 | 国产大学生露脸激情 |