Problem A.Til the Cows Come Home
d.点N到点1的最短路径
s.
c.Dijkstra算法+堆优化

/* Dijkstra算法+堆优化 使用优先队列优化,复杂度O(E log E) 使用优先队列优化Dijkstra算法 复杂度O(E log E) 注意对vector<Edge>E[MAXN]进行初始化后加边 */ #include<iostream> #include<stdio.h> #include<vector> #include<string.h> #include<queue> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=1024; struct qnode{ int v; int c; qnode(int _v=0,int _c=0):v(_v),c(_c){} bool operator <(const qnode &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 dist[MAXN]; //点的编号从1开始 void Dijkstra(int n,int start){ memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++)dist[i]=INF; priority_queue<qnode>que; while(!que.empty())que.pop(); dist[start]=0; que.push(qnode(start,0)); qnode tmp; while(!que.empty()){ tmp=que.top(); que.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]&&dist[v]>dist[u]+cost){ dist[v]=dist[u]+cost; que.push(qnode(v,dist[v])); } } } } void addedge(int u,int v,int w){ E[u].push_back(Edge(v,w)); } int main(){ int T,N; int u,v,w; while(~scanf("%d%d",&T,&N)){ for(int i=1;i<=N;++i){ E[i].clear(); } for(int i=0;i<T;++i){ scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } Dijkstra(N,N); printf("%d ",dist[1]); } return 0; }
Problem B.Frogger(不错)
d.湖中有很多石头,两只青蛙分别位于两块石头上。其中一只青蛙要经过一系列的跳跃,先跳到其他石头上,最后跳到另一只青蛙那里。目的是求出所有路径中最大变长的最小值(就是在到达目的地的路径中,找出青蛙需要跳跃的最大边长的最小的值)。
s.Dijkstra单源最短路的变形,不是求最短路径了,而是求路径中最大的一条边最小,修改一下代码比较部分就行了。
c.Dijkstra单源最短路

/* Dijkstra单源最短路 权值必须是非负 单源最短路径,Dijkstra算法,邻接矩阵形式,复杂度为O(n^2) 求出源beg到所有点的最短路径,传入图的顶点数,和邻接矩阵cost[][] 返回各点的最短路径lowcost[],路径pre[].pre[i]记录beg到i路径上的父结点,pre[beg]=-1 可更改路径权类型,但是权值必须为非负 */ #include<iostream> #include<stdio.h> #include<math.h> using namespace std; const int MAXN=205; #define typec double const typec INF=5000000;//防止后面溢出,这个不能太大 bool vis[MAXN]; int pre[MAXN]; void Dijkstra(typec cost[][MAXN],typec lowcost[],int n,int beg){ for(int i=0;i<n;i++){ lowcost[i]=INF;vis[i]=false;pre[i]=-1; } lowcost[beg]=0; for(int j=0;j<n;j++){ int k=-1; double Min=INF; for(int i=0;i<n;i++) if(!vis[i]&&lowcost[i]<Min){ Min=lowcost[i]; k=i; } if(k==-1)break; vis[k]=true; for(int i=0;i<n;i++) if(!vis[i]&&lowcost[k]<lowcost[i]&&cost[k][i]<lowcost[i]){ lowcost[i]=lowcost[k]>cost[k][i]?lowcost[k]:cost[k][i]; pre[i]=k; } } } int main(){ int n; double x[MAXN],y[MAXN]; double cost[MAXN][MAXN]; double lowcost[MAXN]; int C=0; while(~scanf("%d",&n)){ if(n==0)break; for(int i=0;i<n;++i){ scanf("%lf%lf",&x[i],&y[i]); } for(int i=0;i<n;++i){ for(int j=0;j<n;++j){ cost[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); } } Dijkstra(cost,lowcost,n,0); printf("Scenario #%d ",++C); printf("Frog Distance = %.3f ",lowcost[1]); printf(" "); } return 0; }
Problem C.Heavy Transportation
d.和上个题相反,求路径中最小的一条边最大
s.和上个题类似。不过用下面这个堆优化的模板时,注意要修改下优先队列的优先级,这个题是最大值优先。
c.Dijkstra算法+堆优化

/* Dijkstra算法+堆优化 使用优先队列优化,复杂度O(E log E) 使用优先队列优化Dijkstra算法 复杂度O(E log E) 注意对vector<Edge>E[MAXN]进行初始化后加边 */ #include<iostream> #include<stdio.h> #include<vector> #include<string.h> #include<queue> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=1024; struct qnode{ int v; int c; qnode(int _v=0,int _c=0):v(_v),c(_c){} bool operator <(const qnode &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 dist[MAXN]; //点的编号从1开始 void Dijkstra(int n,int start){ memset(vis,false,sizeof(vis)); //for(int i=1;i<=n;i++)dist[i]=INF; memset(dist,0,sizeof(dist));//这里不是初始化为INF了 priority_queue<qnode>que; while(!que.empty())que.pop(); dist[start]=INF;//出发点设为最大 que.push(qnode(start,INF)); qnode tmp; while(!que.empty()){ tmp=que.top(); que.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]&&dist[v]<dist[u]&&dist[v]<cost){ dist[v]=dist[u]<cost?dist[u]:cost; que.push(qnode(v,dist[v])); } } } } void addedge(int u,int v,int w){ E[u].push_back(Edge(v,w)); } int main(){ int T; int n,m; int u,v,w; int C=0; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ E[i].clear(); } for(int i=0;i<m;++i){ scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } Dijkstra(n,1); printf("Scenario #%d: ",++C); printf("%d ",dist[n]); printf(" "); } return 0; }