[概率期望]做題記錄-換教室
阿新 • • 發佈:2022-05-25
單源最短路徑演算法,其實就是進行鬆馳的演算法。
有Dijkstra/Bellman ford/SPFA 這三種演算法
如圖所示:
演算法模板:
共用程式碼
#define NMAX 105 #define EMAX 10005 int head[NMAX]; int dist[NMAX]; int ver[EMAX]; int nxt[EMAX]; int wi[EMAX]; int tot; void add(int u,int v,int w){ ver[++tot] = v; nxt[tot] = head[u]; head[u] = tot; wi[tot] = w; } bool relax(int u,int v,int w){ if ( dist[v] > dist[u] + w ){ dist[v] = dist[u] + w; return true; } return false; } void reset(){ memset(ver,0,sizeof(ver)); memset(head,0,sizeof(head)); memset(wi,0,sizeof(wi)); memset(nxt,0,sizeof(nxt)); tot = 0; }
Bellman ford
int bellmanford(int n,int source,int target){ dist[source] = 0; for( int i=1;i<n;i++ ){ bool flag = false;//tle解決方案 for(int u=1;u<=n;++u){ for( int e=head[u];e>0;e=nxt[e] ){ int v = ver[e]; int w = wi[e]; flag = relax(u,v,w) || flag; } } if ( !flag ) break; } return dist[target]; }
spfa
int spfa(int n,int source,int to){ memset(bv,0,sizeof(bv)); dist[source] = 0; list<int> li; li.push_back(source); //bv是用來判斷是否在佇列中的 //並不是 是否已經被訪問過。這點與dijkstra不同 bv[source] = true; while(!li.empty()){ int u = li.front(); li.pop_front(); bv[u] = false; for(int e=head[u];e;e=nxt[e]){ int v = ver[e]; if(dist[v]>dist[u] + wi[e]){ dist[v] =dist[u] + wi[e]; if ( !bv[v]){ li.push_back(v); bv[v] = true; } } } } return dist[to]; }
Dijkstra
int dijkstra(int n,int source,int to){
memset(bv,0,sizeof(bv));
dist[source] = 0;
priority_queue<pair<int,int>> q;
q.push(pair<int,int>(0,source));
while(!q.empty()){
int u = q.top().second;
q.pop();
if ( bv[u]) continue;
bv[u] = true;
for( int e=head[u];e>0;e=nxt[e]){
int v = ver[e];
if ( dist[v] > dist[u] + wi[e]) {
dist[v] = dist[u] + wi[e];
q.push(pair<int,int>(-dist[v],v));
}
}
}
return dist[to];
}