題意:給定一個無向稀疏圖,有些節點裏面有牛,問你求一點 全部牛到這點的路程和最小node
解題思路:1)floyd 接受不了,極難優化,因此就有 n次 優先隊列優化的dijkstra 算法,複雜度大概爲V*V*lgV + V*E (其實這種方法接近算法導論上的johnson算法)ios
解題代碼:算法
1 /* 2 ID: dream.y1 3 PROG: butter 4 LANG: C++ 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <queue> 9 #include <vector> 10 #include <climits> 11 using namespace std; 12 const int Ni = 1000; 13 const int INF = 1<<27; 14 struct node{ 15 int x,d; 16 node(){} 17 node(int a,int b){x=a;d=b;} 18 bool operator < (const node & a) const 19 { 20 if(d==a.d) return x<a.x; 21 else return d > a.d; 22 } 23 }; 24 vector<node> eg[Ni]; 25 int dis[Ni],n; 26 void Dijkstra(int s) 27 { 28 int i; 29 for(i=0;i<=n;i++) dis[i]=INF; 30 dis[s]=0; 31 priority_queue<node> q; 32 q.push(node(s,dis[s])); 33 while(!q.empty()) 34 { 35 node x=q.top();q.pop(); 36 for(i=0;i<eg[x.x].size();i++) 37 { 38 node y=eg[x.x][i]; 39 if(dis[y.x]>x.d+y.d) 40 { 41 dis[y.x]=x.d+y.d; 42 q.push(node(y.x,dis[y.x])); 43 } 44 } 45 } 46 } 47 int ans[1000]; 48 int main() 49 { 50 freopen("butter.in","r",stdin); 51 freopen("butter.out","w",stdout); 52 int a,b,d,p,c; 53 scanf("%d %d %d",&p,&n,&c); 54 for(int i = 1;i <= p; i ++) 55 scanf("%d",&ans[i]); 56 for(int i=0;i<= n;i++) eg[i].clear(); 57 while(c--) 58 { 59 scanf("%d%d%d",&a,&b,&d); 60 eg[a].push_back(node(b,d)); 61 eg[b].push_back(node(a,d)); 62 } 63 int min = INT_MAX; 64 for(int i = 1;i <= n ;i ++ ) 65 { 66 Dijkstra(i); 67 int tsum = 0 ; 68 for(int j = 1;j <= p;j ++) 69 tsum += dis[ans[j]]; 70 if(tsum < min) 71 min = tsum ; 72 } 73 printf("%d\n",min); 74 return 0; 75 }
2)SPFA 這種算法在本題上的表現比優先隊列優化的dijkstra 更快,可是它的算法表現一般不穩定。ide
解題代碼:優化
1 // File Name: 2544_1.cpp 2 // Author: darkdream 3 // Created Time: 2014年04月04日 星期五 22時37分45秒 4 /* 5 ID: dream.y1 6 PROG: butter 7 LANG: C++ 8 */ 9 #include<vector> 10 #include<list> 11 #include<map> 12 #include<set> 13 #include<deque> 14 #include<stack> 15 #include<bitset> 16 #include<algorithm> 17 #include<functional> 18 #include<numeric> 19 #include<utility> 20 #include<sstream> 21 #include<iostream> 22 #include<iomanip> 23 #include<cstdio> 24 #include<cmath> 25 #include<cstdlib> 26 #include<cstring> 27 #include<ctime> 28 #include<climits> 29 #include<queue> 30 using namespace std; 31 32 struct node{ 33 int x, d ; 34 node() 35 {} 36 node(int p,int q) 37 { 38 x = p; 39 d = q; 40 } 41 }; 42 vector <node> edge[1000]; 43 int n , m ; 44 int dis[1000]; 45 queue <int> lis; 46 int SPFA(int s) 47 { 48 for(int i = 1;i <= n;i ++) dis[i] = 1 << 27; 49 dis[s] = 0 ; 50 lis.push(s); 51 while(!lis.empty()) 52 { 53 int k = lis.front(); 54 // printf("%d\n",k); 55 lis.pop(); 56 int n = edge[k].size(); 57 for(int i = 0 ;i < n ;i ++) 58 { 59 if(dis[edge[k][i].x] > dis[k] + edge[k][i].d) 60 { 61 dis[edge[k][i].x] = dis[k] + edge[k][i].d; 62 lis.push(edge[k][i].x); 63 } 64 } 65 } 66 return 1; 67 } 68 int main(){ 69 freopen("butter.in","r",stdin); 70 freopen("butter.out","w",stdout); 71 int p ; 72 scanf("%d %d %d",&p,&n,&m); 73 74 int a[3000]; 75 for(int i = 1;i <= p;i ++) 76 scanf("%d",&a[i]); 77 for(int i =1 ;i <= n;i++) 78 edge[i].clear(); 79 for(int i = 1;i <= m ;i ++) 80 { 81 int a, b, c; 82 scanf("%d %d %d",&a,&b,&c); 83 edge[a].push_back(node(b,c)); 84 edge[b].push_back(node(a,c)); 85 } 86 int min = INT_MAX; 87 for(int i= 1;i <= n;i ++) 88 { SPFA(i); 89 int tsum = 0 ; 90 for(int j = 1;j <= p ;j ++) 91 tsum += dis[a[j]]; 92 if(tsum < min ) 93 min = tsum ; 94 } 95 printf("%d\n",min); 96 return 0; 97 }