题目:Emergency
我的代码:
//ng了70%,求最短路径条数的方法参照了参考代码的,但是也没能通过
#include<iostream>
#include<vector>
using namespace std;
int const MaxVertex = 500;
#define Vertex int
#define EdgeWeight int
#define Infinity 65535
//边的定义
typedef struct{
Vertex vf;
Vertex vt;
EdgeWeight weight;
}Edge;
//图的定义
typedef struct{
int vn; //节点数
int en; //边数
EdgeWeight GraphMatrix[MaxVertex][MaxVertex]; //图矩阵---这里的MaxVertea需要为常量
int rescue[MaxVertex]; //救援队矩阵
}Graph;
//先初始化图
Graph* CreatGraph(Graph *G){
for(int i = 0;i < MaxVertex;i++){
G->rescue[i]=0;
for(int j = 0;j < MaxVertex;j++){
G->GraphMatrix[i][j] = Infinity;
}
}
return G;
}
//根据输入构建图
Graph* BuildGraph(Graph *G,Vertex &V1,Vertex &V2){
cin>>G->vn>>G->en>>V1>>V2;
Edge *E;
E = new Edge;
for(int i = 0;i < G->vn;i++)
cin>>G->rescue[i];
for(int i = 0;i < G->en;i++){
cin>>E->vf>>E->vt>>E->weight;
G->GraphMatrix[E->vf][E->vt] = E->weight; //注意是无向图
G->GraphMatrix[E->vt][E->vf] = E->weight;
}
return G;
}
//返回目前为止路径累积最短的节点
Vertex MinPathV(Graph *G,int Dist[],int Collect[]){
int Min = Infinity;
int pos;
for(int i = 0;i < G->vn;i++){
if(Collect[i] == false && Dist[i] < Min) { //在未扫描过的顶点中选择
pos = i;
Min = Dist[i]; //只有还有没有访问过的节点时候,Min才会更新
}
}
if(Min < Infinity) return pos;
else return -1;
}
//迪杰斯特拉算法
//**collected[]是判断哪些节点已经被访问的矩阵、path[v]是存储v节点的上一个节点的矩阵
//**dist[v]是存储到v的路径代价,Res[]是存储到v的路径的救援队数量**//
void Djs(Graph *G,Vertex v1,int Collect[],int Path[],int Dist[],int Res[],vector<int>count){
for(int i = 0;i < G->vn;i++){
Dist[i] = G->GraphMatrix[v1][i];
Path[i] = v1;
Res[i] = G->rescue[v1] + G->rescue[i];
Collect[i] = false;
}
Collect[v1] = true;Dist[v1] = 0;
Vertex v;
while(true){
v = MinPathV(G,Dist,Collect);
if(v == -1) break; //当v中找不到没有访问过的节点,则退出while循环
Collect[v] = true; //注意放到已访问集合中是在判断为最小值之后
for(int i = 0;i < G->vn;i++){
if(Collect[i] == false && Dist[i] > Dist[v] + G->GraphMatrix[v][i]){
Dist[i] = Dist[v] + G->GraphMatrix[v][i];
Path[i] = v;
Res[i] = Res[v] + G->rescue[i];
count[i] = count[v]; //直接赋值
}
else if(Collect[i] == false && Dist[i] == Dist[v] + G->GraphMatrix[v][i]){
count[i] += count[v]; //原来的加上新增的
if(Res[i] < Res[v] + G->rescue[i]){
Path[i] = v;
Res[i] = Res[v] + G->rescue[i];
}
}
}
}
}
//按要求寻找最短路径
void FindThePath(Graph *G,Vertex &s,Vertex &d){
Vertex Collect[G->vn];
Vertex Path[G->vn];
Vertex Dist[G->vn];
Vertex Res[G->vn];
vector<int>count(G->vn,1);
Djs(G,s,Collect,Path,Dist,Res,count);
cout<<count[d]<<' '<<Res[d];
}
int main(){
Graph *G;
G = new Graph;
Vertex S,D;
G = CreatGraph(G);
G = BuildGraph(G,S,D);
FindThePath(G,S,D);
}
评注:
第二次做图的题目,遇到很多问题
(1)宏定义的时候再句末不需要加逗号
(2)定义数据的时候数据大小不能是一个变量名,如果要填变量名,要定义成const常量
(3)在用引用作为函数形参,然后把图结构体传进去的时候,编译器直接死机,后面改成用指针,不会有这个问题
(4)定义指针后记得要初始化指针
参考代码:
链接:https://www.nowcoder.com/questionTerminal/8d3c64413a74486f87de8ab1285fe04f
来源:牛客网
//PAT和牛客都AC了,有疑问可以评论
#include<iostream>
#include<algorithm>
#define inf 65535
using namespace std;
int n,m,s,t,used[500]={0},cost[500][500],mincost[500],path[500],amount[500],maxget[500];
void dijkstra(int s)
{
int u,v,i,j;
fill(path,path+500,1); //这个函数挺强
mincost[s]=0;
while(1)
{
v=-1;
for(u=0;u<n;u++)
if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u;
if(v==-1) break;
used[v]=1;
for(u=0;u<n;u++)
{
if(!used[u]&&mincost[u]>mincost[v]+cost[v][u])
{
mincost[u]=mincost[v]+cost[v][u];
maxget[u]=maxget[v]+amount[u];
path[u]=path[v];
}
else if(!used[u]&&mincost[u]==mincost[v]+cost[v][u])
{
path[u]+=path[v];
maxget[u]=max(maxget[u],maxget[v]+amount[u]);
}
}
}
}
int main()
{
int i,j,u,v;
for(i=0;i<500;i++)
for(j=0;j<500;j++)
cost[i][j]=inf; //初始化图矩阵
cin>>n>>m>>s>>t;
for(i=0;i<n;i++)
{
mincost[i]=inf; //到每个地方的最小长度
cin>>amount[i]; //amount为每个地方的营救队数量
maxget[i]=amount[i];
}
for(i=0;i<m;i++)
{
cin>>u>>v;
cin>>cost[u][v];
cost[v][u]=cost[u][v];
}
dijkstra(s);
cout<<path[t]<<' '<<maxget[t];
return 0;
}
评注:
(1)并没有用结构体来描述图的机构,只是用数据来实现
(2)fill(a,a+n,x)这个给数组初始化的方法要学会使用
(3)max()的方法要学会使用,上面说的两个函数都是在#include<algorithm>头文件里面