圖論最短路——spfa
阿新 • • 發佈:2018-09-25
print 操作 標記 pen play hide man mage 隊列
今天開始圖論的最短路的最後復習,今天自己手打spfa雖然看了一眼書,但是也算是自己打出來的,畢竟很久沒打了,而且還是一遍a代碼下來15min左右就搞完了,成就感++。所以呢來篇博客記錄一下。
香甜的黃油,當年做的時候吃了不少苦頭現在完全會打了,下面是當時我的代碼:
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<cmath> #include<ctime> #includeView Code<iostream> #include<string> using namespace std; const int maxn=1002,inf=1000000000; int n,p,c,a,b,d,t,dist[maxn],s1[maxn],inq[maxn]; vector<int>g[maxn],w[maxn]; void spfa(int s) { queue<int>a;//一個隊列a for(int i=1;i<=p;i++)//循環4個牧場都附極大值 dist[i]=inf; memset(inq,0,sizeof(inq));//清空inp dist[s]=0;//把到當前的牧場距離設為0,畢竟是自己到自己 a.push(s);//進隊 inq[s]=1;//使其為1 while(!a.empty())//如果隊列不為空 { int i=a.front();//返回隊首元素 a.pop();//彈出隊首 inq[i]=0;//使其為0 for(int k=0;k<g[i].size();k++)//當前的牧場和其余的牧場相連 { int j=g[i][k];//取i到j的牧場號詢問其距離 if(dist[i]+w[i][k]<dist[j])//如果當前距離和i到k的距離小於j松弛操作 { dist[j]=dist[i]+w[i][k];//松弛 if(inq[j]!=0) continue;//詢問是否在隊列之中 inq[j]=1;//不在的話再次標記 a.push(j);//使當前的點進隊好像bfs但不是bfs多次進隊 } } } } int main() { //freopen("1.in","r",stdin); scanf("%d%d%d",&n,&p,&c);//n為奶牛所在的牧場號,p為4個牧場,c為5個牧場的關系 memset(s1,0,sizeof(s1));//s1存的是奶牛的牧場位置; for(int i=1;i<=n;i++) { scanf("%d",&t);//牛 s1[t]++;//牧場 } for(int i=1;i<=c;i++) { scanf("%d%d%d",&a,&b,&d);//a與b之間的距離為d g[a].push_back(b);//擴邊 g[b].push_back(a); w[a].push_back(d);//二次擴邊 w[b].push_back(d); } int ans=inf;//附最大值 for(int i=1;i<=p;i++)//枚舉每一個牧場為起點 { spfa(i);//當黃油放在第i個牧場時來一個一個判斷;跑距離 int sum=0; for(int j=1;j<=p;j++) { if(!s1[j]) continue; sum+=dist[j]*s1[j]; //計算奶牛到牧場的距離和 } ans=min(sum,ans); //取最小值 } printf("%d",ans); return 0; }
註釋很多很多,主要因為當時的不理解。
下面是本人今天的代碼!!!
#include<iostream> #include<cstring> #include<string> #include<cstdio> #include<cmath> #include<iomanip> #include<algorithm> #include<stack> #include<ctime> #include<vector> #include<queue> #include<map> #define inf 10000000 using namespace std; const int maxn=5000; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int b[maxn],ver[maxn],lin[maxn],nex[maxn],len=0,e[maxn],minn=inf,dis[maxn],q[maxn]; bool vis[maxn]; void add(int x,int y,int z) { ver[++len]=y; nex[len]=lin[x]; lin[x]=len; e[len]=z; } int n,m,k,h,t; void spfa(int x) { memset(vis,0,sizeof(vis)); memset(dis,10,sizeof(dis)); memset(q,0,sizeof(q)); dis[x]=0;vis[x]=1;q[1]=x; h=0,t=1; while(h<=t) { int tn=q[++h];vis[tn]=0; for(int i=lin[tn];i;i=nex[i]) { int tmp=ver[i]; if(dis[tn]+e[i]<dis[tmp]) { dis[tmp]=dis[tn]+e[i]; if(vis[tmp]!=1) { q[++t]=tmp; vis[tmp]=1; } } } } } int main() { freopen("1.in","r",stdin); k=read();m=read();n=read(); memset(b,0,sizeof(b)); for(int i=1;i<=k;i++){int x;x=read();b[x]++;} for(int i=1;i<=n;i++) { int x,y,z; x=read();y=read();z=read(); add(x,y,z); add(y,x,z); } for(int i=1;i<=m;i++) { int ans=0; spfa(i); for(int j=1;j<=m;j++) { if(b[j]!=0) ans+=dis[j]*b[j]; } minn=min(ans,minn); } printf("%d\n",minn); return 0; }View Code
思路很清晰的打完了哈哈。
莫聽穿林打葉聲,何妨吟嘯且徐行。
圖論最短路——spfa