例题:hdu的1874
FLOYD
a->b有两种走法,1、a->k->b,2、a->b
这是主要思想。那每次保留最短路径即可。
dp[i][j] = min(dp[i][j] , dp[i][k] + dp[k][j])
1 #include<iostream> 2 #include<vector> 3 #include<queue> 4 #include<algorithm> 5 using namespace std; 6 const int maxn = 205; 7 8 int n,m; 9 int mp[maxn][maxn]; 10 11 void init(int n){ 12 for(int i = 0; i < n ;i++){ 13 for(int j = 0 ; j < n ;j++){ 14 if(i == j) 15 mp[i][j] = 0; 16 else 17 mp[i][j] = 1e9; 18 } 19 } 20 } 21 22 int main(){ 23 24 while(cin>>n>>m){ 25 init(n); 26 int x,y,z; 27 28 for(int i = 1; i <= m ;i++){ 29 cin>>x>>y>>z; 30 mp[x][y] = min(z,mp[x][y]); 31 mp[y][x] = min(z,mp[y][x]); 32 } 33 34 int s,t; 35 cin>>s>>t; 36 37 for(int k = 0; k < n ;k++){ 38 for(int i = 0; i < n ;i++){ 39 for(int j = 0; j < n ;j++){ 40 mp[i][j] = min(mp[i][j],mp[i][k] + mp[k][j]); 41 //cout<<mp[i][j]<<endl; 42 } 43 } 44 } 45 //cout<<mp[1][2]<<endl; 46 if(mp[s][t] == 1e9) 47 cout<<-1<<endl; 48 else 49 cout<<mp[s][t]<<endl; 50 } 51 52 return 0; 53 }
SPFA
基于dp的思想。十分有趣的板子
e[] 存边
d[] 存距离
inq[] 判断是否在queue里。
主要的dp思想就是
dp[v] = max(dp[now] + e[now][i].second , dp[v])
1 #include<iostream> 2 #include<stack> 3 #include<vector> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 const int maxn = 2e5+7; 8 9 vector< pair<int,int> > e[maxn]; 10 11 int n,m; 12 int d[maxn],inq[maxn]; 13 14 void init(){ 15 for(int i = 0; i < maxn; i++) 16 e[i].clear(); 17 for(int i = 0 ;i < maxn ; i++) 18 inq[i] = 0; 19 for(int i = 0 ; i < maxn ; i++) 20 d[i] = 1e9; 21 } 22 23 int main(int argc, const char * argv[]) { 24 while(cin>>n>>m){ 25 init(); 26 int x,y,z; 27 for(int i = 0; i < m ;i++){ 28 cin>>x>>y>>z; 29 e[x].push_back(make_pair(y,z)); 30 e[y].push_back(make_pair(x,z)); 31 } 32 int s,t; 33 cin>>s>>t; 34 queue<int>Q; 35 Q.push(s);d[s] = 0 ;inq[s] = 1; 36 while( !Q.empty() ){ 37 int now = Q.front(); 38 Q.pop(); 39 inq[now] = 0; 40 for(int i = 0; i < e[now].size() ; i++){ 41 int v = e[now][i].first; 42 if(d[v] > d[now] + e[now][i].second){ 43 d[v] = d[now] + e[now][i].second; 44 if(inq[v] == 1) 45 continue; 46 inq[v] = 1; 47 Q.push(v); 48 } 49 } 50 51 } 52 if(d[t] == 1e9) 53 cout<<-1<<endl; 54 else{ 55 cout<<d[t]<<endl; 56 } 57 } 58 return 0; 59 }
更新一下kb大神的板子。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5+7; const int inf = 0x3f3f3f3f; struct Edge{ int v; int cost; Edge(int _v = 0,int _cost = 0):v(_v),cost(_cost){} }; vector<Edge> e[maxn]; void addedge(int u,int v,int w){ e[u].push_back(Edge(v,w)); } bool vis[maxn]; int cnt[maxn]; int dis[maxn]; int n,m,c; bool spfa(int s){ memset(vis,false,sizeof(vis)); for(int i = 1; i <= n; i++) dis[i] = inf; vis[s] = true; dis[s] = 0; queue<int> Q; while(!Q.empty()) Q.pop(); Q.push(s); memset(cnt,0,sizeof(cnt)); cnt[s] = 1; while(!Q.empty()){ int u = Q.front(); Q.pop(); vis[u] = false; for(int i = 0; i < e[u].size();i++){ int v = e[u][i].v; if(dis[v] > dis[u] + e[u][i].cost){ dis[v] = dis[u] + e[u][i].cost; if(!vis[v]){ vis[v] = true; Q.push(v); if(++cnt[v] > n) return false; //cnt[i] } } } } return true; }
DIJSTRA
其实就是在spfa上做了优先队列的改进,省略了inq[]数组。
第一次用这个优先队列,感觉很妙。
1 #include<iostream> 2 #include<stack> 3 #include<vector> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 const int maxn = 2e5+7; 8 9 vector< pair<int,int> > e[maxn]; 10 11 int n,m; 12 int d[maxn]; 13 14 void init(){ 15 for(int i = 0; i < maxn; i++) 16 e[i].clear(); 17 for(int i = 0 ; i < maxn ; i++) 18 d[i] = 1e9; 19 } 20 21 int main(int argc, const char * argv[]) { 22 while(cin>>n>>m){ 23 init(); 24 int x,y,z; 25 for(int i = 0; i < m ;i++){ 26 cin>>x>>y>>z; 27 e[x].push_back(make_pair(y,z)); 28 e[y].push_back(make_pair(x,z)); 29 } 30 int s,t; 31 cin>>s>>t; 32 priority_queue <pair<int,int> >Q; 33 d[s] = 0; 34 Q.push( make_pair(-d[s],s) ); 35 while( !Q.empty() ){ 36 int now = Q.top().second; 37 Q.pop(); 38 39 for(int i = 0; i < e[now].size() ; i++){ 40 int v = e[now][i].first; 41 if(d[v] > d[now] + e[now][i].second){ 42 d[v] = d[now] + e[now][i].second; 43 Q.push( make_pair(-d[v],v)); 44 } 45 } 46 47 } 48 if(d[t] == 1e9) 49 cout<<-1<<endl; 50 else{ 51 cout<<d[t]<<endl; 52 } 53 } 54 return 0; 55 }
kb大神的板子
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5+7; const int inf = 0x3f3f3f3f; struct node{ int v; int c; node(int _v = 0,int _c = 0):v(_v),c(_c){} bool operator < (const node &r)const{ return c > r.c; } }; struct Edge{ int v,cost; Edge(int _v = 0, int _cost = 0):v(_v),cost(_cost){} }; vector< Edge > e[maxn]; bool vis[maxn]; int dis[maxn]; int n,m,c; void addedge(int u,int v,int w){ e[u].push_back(Edge(v,w)); } void dij(int s){ memset(vis,false,sizeof(vis)); for(int i = 1; i <= n ;i++) dis[i] = inf; priority_queue <node> Q; while(!Q.empty()) Q.pop(); dis[s] = 0; Q.push(node(s,0)); node tmp; while( !Q.empty() ){ tmp = Q.top(); Q.pop(); int u = tmp.v; if(vis[u]) continue; vis[u] = true; for(int i = 0; i < e[u].size(); i++){ int v = e[tmp.v][i].v; int cost = e[u][i].cost; if(!vis[v] && dis[v] > dis[u] + cost){ dis[v] = dis[u] + cost; Q.push(node(v,dis[v])); } } } }