hdu1874 暢通工程續
陳年水題,老少皆宜,最短路的入門作業
但是換個刷法,會更有意思
最短路的 Floyd 演算法:
#include<stdio.h>#include<string.h>#define find_min(a,b) a<b?a:b#define MAX 0xfffffffint n,m,map[201][201],dist[201],vis[201];void getmap(){int i,j,a,b,c;for(i=0;i<n;i++){for(j=0;j<n;j++)map[i][j]=(i==j?0:MAX);}for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);map[a][b]=map[b][a]=find_min(map[a][b],c);}}void floyd(int sp,int ep){for(int k=0;k<n;k++){for(int i=0;i<n;i++)for(int j=0;j<n;j++)map[i][j]=find_min(map[i][j],map[i][k]+map[k][j]);}printf("%d\n",map[sp][ep]<MAX?map[sp][ep]:-1);}int main(){int s,e;while(~scanf("%d%d",&n,&m)){getmap();scanf("%d%d",&s,&e);floyd(s,e);}return 0;}
最短路dijkstra演算法的 鄰接陣實現:
#include<stdio.h>#include<string.h>#define find_min(a,b) a<b?a:bconst int MAX = 0xfffffff;const int N = 210;int n,m,map[N][N],dist[N],vis[N];void getmap(){int i,j,a,b,c;memset(vis,0,sizeof(vis));for(i=0;i<n;i++){for(j=0;j<n;j++)map[i][j] = (i==j?0:MAX);}for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);map[a][b]=map[b][a]=find_min(map[a][b],c);}}void dij(int start,int to){int i,cur,next;for(i=0;i<n;dist[i++]=MAX);dist[start]=0;cur=start;while(1){vis[cur]=1;int min=MAX;for(i=0;i<n;i++){if(vis[i])continue;if(dist[i]-map[i][cur]>dist[cur])dist[i]=map[i][cur]+dist[cur];if(dist[i]<min){min=dist[i]; next=i;}}cur=next;if(cur==to)break;if(min==MAX)break;}printf("%d\n",dist[to]<MAX?dist[to]:-1);}int main(){int sp,ep;while(~scanf("%d%d",&n,&m)){getmap();scanf("%d%d",&sp,&ep);dij(sp,ep);}return 0;}
最短路dijkstra演算法 的鄰接表實現:
#include<stdio.h>#include<string.h>const int MAX = 0xfffffff;const int N =210;struct Edge{int s,e,v;int next;}edge[1001];int n,m,e_num,head[N],dist[N],vis[N];void AddEdge(int a,int b,int c){edge[e_num].s=a; edge[e_num].e=b; edge[e_num].v=c;edge[e_num].next=head[a]; head[a]=e_num++;edge[e_num].s=b; edge[e_num].e=a; edge[e_num].v=c;edge[e_num].next=head[b]; head[b]=e_num++;}void getmap(){int i,a,b,c;e_num=0;memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));for(i=0;i<n;dist[i++]=MAX);for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);AddEdge(a,b,c);}}void dij(int sp,int ep){int i,cur,next;dist[sp]=0;vis[sp]=1;cur=sp;while(1){if(cur==ep)break;vis[cur]=1;for(i=head[cur];i!=-1;i=edge[i].next)//更新和cur相鄰點的dist[]{int u=edge[i].e;if(vis[u])continue;if(dist[u] - edge[i].v > dist[cur])dist[u]=edge[i].v+dist[cur];}int min=MAX;for(i=0;i<n;i++)//找到最近的點,作為下一個cur值{if(vis[i])continue;if( dist[i] < min){min=dist[i]; next=i;}}cur=next;if(min==MAX)break;}printf("%d\n",dist[ep]<MAX?dist[ep]:-1);}int main(){int sp,ep;while(~scanf("%d%d",&n,&m)){getmap();scanf("%d%d",&sp,&ep);dij(sp,ep);}return 0;}
最短路spfa演算法 :
#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;const int MAX = 0xffffff;const int N = 201;struct Edge{int s,e,v;int next;}edge[1001];int n,m,e_num,vis[N],head[N],dist[N];void AddEdge(int a,int b,int c){edge[e_num].s=a; edge[e_num].e=b; edge[e_num].v=c;edge[e_num].next=head[a]; head[a]=e_num++;edge[e_num].s=b; edge[e_num].e=a; edge[e_num].v=c;edge[e_num].next=head[b]; head[b]=e_num++;}void getmap(){int i,a,b,c;e_num=0;memset(vis,0,sizeof(vis));memset(head,-1,sizeof(head));for(i=0;i<n;dist[i++]=MAX);for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);AddEdge(a,b,c);}}void spfa(int sp,int ep){queue <int> q;q.push(sp);vis[sp]=1;dist[sp]=0;while(!q.empty()){int cur=q.front();q.pop();vis[cur]=0;for(int i=head[cur];i!=-1;i=edge[i].next){int u=edge[i].e;if(dist[u]>dist[cur]+edge[i].v){dist[u]=dist[cur]+edge[i].v;if(!vis[u]){q.push(u);vis[u]=1;}}}}printf("%d\n",dist[ep]<MAX?dist[ep]:-1);}int main(){int sp,ep;while(~scanf("%d%d",&n,&m)){getmap();scanf("%d%d",&sp,&ep);spfa(sp,ep);}return 0;}
dij + 優先隊列 最佳化:
#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;const int N = 1001;const int MAX = 0xfffffff;struct Node{int id,val;bool operator < (const Node &a) const{return a.val < val;}};struct Edge{int s,e,v;int next;}edge[4*N];int n,m,e_num,vis[N],dist[N],head[N];void AddEdge(int a,int b,int c){edge[e_num].s=a; edge[e_num].e=b; edge[e_num].v=c;edge[e_num].next=head[a]; head[a]=e_num++;edge[e_num].s=b; edge[e_num].e=a; edge[e_num].v=c;edge[e_num].next=head[b]; head[b]=e_num++;}void getmap(){int i,a,b,c;e_num=0;memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));for(i=0;i<n;dist[i++]=MAX);for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);AddEdge(a,b,c);}}void dij(int sp,int ep){Node cur,next;priority_queue <Node> q;dist[sp]=0;cur.id=sp; cur.val=0;q.push(cur);while(!q.empty()){cur=q.top();//出隊是選擇val最小的點出隊,不需要再次尋找q.pop();if(cur.id==ep)break;if(vis[cur.id])continue;vis[cur.id]=1;for(int i=head[cur.id];i!=-1;i=edge[i].next){int u=edge[i].e;if(vis[u])continue;if(dist[u] - cur.val > edge[i].v){dist[u]=cur.val + edge[i].v;next.id=u;next.val=dist[u];q.push(next);}}}printf("%d\n",dist[ep]<MAX?dist[ep]:-1);}int main(){int sp,ep;while(~scanf("%d%d",&n,&m)){getmap();scanf("%d%d",&sp,&ep);dij(sp,ep);}return 0;}
刷水其實很有意思,真的是,真的是這樣……