[kuangbin带你飞]专题四 最短路练习 A-E

来源:互联网 发布:淘宝名字能改吗 编辑:程序博客网 时间:2024/05/21 00:19

题目链接:https://vjudge.net/contest/66569#overview

A:

#include <iostream>   #include <queue>  #include <cstdio> using namespace std;  const int maxn=1005;  vector <pair<int,int> >E[maxn];   int dis[maxn];   bool vis[maxn];   void Init()  {      for(int i=0;i<maxn;i++)        E[i].clear(),vis[i]=false,dis[i]=1e9;  }  void spfa(int s,int t){      queue<int>q;      q.push(s);      dis[s]=0;      vis[s]=true;       while(!q.empty())      {          int now=q.front();          q.pop();          vis[now]=false;           for(int i=0;i<E[now].size();i++)           {              int next=E[now][i].first;              if(dis[next]>dis[now]+E[now][i].second)              {                  dis[next]=dis[now]+E[now][i].second;                  if(vis[next])continue;                 vis[next]=true;                  q.push(next);               }           }      }  }int main(){int T,N;while(scanf("%d%d",&T,&N)==2){Init();for(int i=1;i<=T;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);E[x].push_back(make_pair(y,z));E[y].push_back(make_pair(x,z));}spfa(N,1);printf("%d\n",dis[1]);}return 0;} 

B:最短路的变形,求最小边.数据小,可以写个floyd交.

#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>using namespace std;double map[205][205];int x[205];int y[205];double  dis(int i,int j){return sqrt(double(x[i]-x[j])*(x[i]-x[j])+double(y[i]-y[j])*(y[i]-y[j]));}void floyd(int n){for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)    map[i][j]=min(map[i][j],max(map[i][k],map[k][j]));}int main(){   int n,q=1;     while(scanf("%d",&n)==1&&n)      {         memset(map,0x3f,sizeof(map));          for(int i=1; i<=n; i++)              scanf("%d%d",&x[i],&y[i]);          for(int i=1; i<=n; i++)              for(int j=i+1; j<=n; j++)                  map[i][j]=map[j][i]=dis(i,j);          floyd(n);          printf("Scenario #%d\nFrog Distance = %.3f\n\n",q++,map[1][2]);      }  }

C:就是B题的反过来,求最大的边。但是floyd过不了,用了我的dij模版改了下条件。dis[next]=max(dis[next],min(dis[now],cost[now][next])

#include <iostream>   #include <queue>  #include <cstdio>#include <vector>#include <algorithm> using namespace std;  const int maxn=1005; //顶点数自己定   vector <pair<int,int> >E[maxn];//存图   int dis[maxn];   void Init()  {      for(int i=0;i<maxn;i++)        E[i].clear(),dis[i]=0;  }  void Dijkstra(int s,int t)//源点,终点.   {      priority_queue<pair<int,int> >q;          dis[1]=1e9;          q.push(make_pair(dis[1],1));          while(!q.empty())          {              int now=q.top().second;              q.pop();              for(int i=0;i<E[now].size();i++)              {                  int next=E[now][i].first;                  if(dis[next]<min(dis[now],E[now][i].second))                  {                      dis[next]=min(dis[now],E[now][i].second);                      q.push(make_pair(dis[next],next));                  }              }           }  }    int main()  {  int t;     int n,m;    int cas=1;scanf("%d",&t);    while(t--)  {  scanf("%d%d",&n,&m);         Init();          for(int i=0;i<m;i++)          {              int x,y,z;              scanf("%d%d%d",&x,&y,&z);             E[x].push_back(make_pair(y,z));              E[y].push_back(make_pair(x,z));          }          Dijkstra(1,n);           printf("Scenario #%d:\n",cas++);         printf("%d\n",dis[n]);       if(t!=0)       printf("\n");        }    return 0;  }  

D:n个源点,1个x目标点.单源找来回最大的最短路. 回来只要找一次,出发每个点找一次.

#include <cstdio>#include <vector>#include <queue>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1005;vector<pair<int,int> >E[maxn];int dis[maxn]; int go[maxn];void dij(int s){for(int i=0;i<maxn;i++)dis[i]=1e9;dis[s]=0;priority_queue<pair<int,int> >q;q.push(make_pair(-dis[s],s));while(!q.empty()){int now=q.top().second;q.pop();for(int i=0;i<E[now].size();i++){int next=E[now][i].first;if(dis[next]>dis[now]+E[now][i].second){dis[next]=dis[now]+E[now][i].second;q.push(make_pair(-dis[next],next));}} }}int main(){int n,m,x;scanf("%d%d%d",&n,&m,&x);for(int i=0;i<m;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);E[x].push_back(make_pair(y,z));}for(int i=1;i<=n;i++){if(n==x)continue;dij(i),go[i]=dis[x];}dij(x);int ans=-1;for(int i=1;i<=n;i++)ans=max(ans,go[i]+dis[i]);printf("%d\n",ans);}

E:读这种长的英文是真烦,

第一行叫你输4个数 N,M,S,V . N种货币种类(用数字代替) M个城市(每个城市有两种货币可以进行兑换) S(你的钱的种类) V(你的钱数)

接下来M行自然就是6个数代表该城市的信息:货币A,货币B,A->B的汇率,A->B的佣金,B->A的汇率,B->A的佣金.(题目有给兑换公式)

问你有没办法通过一系列货币的转换,最后当货币换回原来货币种类的时候,V变多了。 事实上就是判断正环的问题。那就改下判断负环的一些条件就好了。改下初始值

初始d(S)=V   而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径,用BF判断是第n次循环还变大就有正环,spfa就是入队超过n次说明有正环,这里我用spfa做。。

#include <iostream>#include <cstdio>#include <queue>#include <vector>#include <cstdio>using namespace std;const int maxn=105;int n,m,s;double v;struct exc{double r,c;}; vector<pair<int,exc> >E[maxn];double dis[maxn];bool vis[maxn];int time[maxn];bool spfa(){for(int i=0;i<maxn;i++) vis[i]=false;for(int i=0;i<maxn;i++)dis[i] = 0;for(int i=0;i<maxn;i++)time[i]= 0;dis[s]=v;vis[s]=true;queue<int>q;q.push(s);while(!q.empty()){int now=q.front();q.pop();time[now]++;vis[now]=false;if(time[now]>n) return true;for(int i=0;i<E[now].size();i++){int next=E[now][i].first;double temp=0;temp=(dis[now]-E[now][i].second.c)*(E[now][i].second.r);if(dis[next]<temp){dis[next]=temp;if(vis[next])continue;vis[next]=true;q.push(next);}} }         return false;  }int main(){scanf("%d%d%d%lf",&n,&m,&s,&v);for(int i=1;i<=m;i++){int x,y;double xyr,xyc,yxr,yxc;scanf("%d%d%lf%lf%lf%lf",&x,&y,&xyr,&xyc,&yxr,&yxc);exc temp;temp.r=xyr,temp.c=xyc;E[x].push_back(make_pair(y,temp));temp.r=yxr,temp.c=yxc;E[y].push_back(make_pair(x,temp));}printf("%s",spfa()?"YES":"NO");}

剩下有空补,先去补其他知识.


原创粉丝点击