1003. Emergency
阿新 • • 發佈:2018-11-26
這道題一開始就卡在了題目沒看清這個問題上。題目是最短路徑的變形,但是輸出要求的最短路徑的條數和路徑上結點值的最大和。
#include <stdio.h> #include <stdlib.h> #define MaxVertexNum 500 #define INFINITY 65535 /* 二進位制的2^16,即int型別最大儲存值 */ typedef int ElementType; typedef int WeightType; typedef int Vertex; /* 圖結點 */ struct GNode{ int Nv, Ne; WeightType G[MaxVertexNum][MaxVertexNum]; ElementType Data[MaxVertexNum]; }; typedef struct GNode *PtrToGNode; typedef PtrToGNode MGraph; MGraph CreateGraph(int VertexNum); MGraph BuildGraph(int M, int N); void Dijkstra_X(MGraph Graph, int path[], int dist[], Vertex S, Vertex E); Vertex FindMindist(MGraph Graph, int dist[], int collected[]); int main() { //freopen("C:\\Users\\ChanWunsam\\Desktop\\pat\\pat_in.txt","r",stdin); //freopen("C:\\Users\\ChanWunsam\\Desktop\\pat\\pat_out.txt","w",stdout); int M, N, C1, C2; int dist[MaxVertexNum], path[MaxVertexNum], Sum; MGraph Graph; Vertex W; scanf("%d %d %d %d", &M, &N, &C1, &C2); Graph=BuildGraph(M, N); if(C1==C2) /* 如果起始地和目的地相同 */ { printf("%d %d", 1, Graph->Data[C1]); } else Dijkstra_X(Graph, dist, path, C1, C2); return 0; } MGraph CreateGraph(int VertexNum) { Vertex V, W; MGraph Graph; Graph=(MGraph)malloc(sizeof(struct GNode)); Graph->Nv=VertexNum; Graph->Ne=0; for(V=0; V<VertexNum; V++) { Graph->Data[V]=-1; for(W=0; W<VertexNum; W++) { Graph->G[V][W]=INFINITY; } } return Graph; } MGraph BuildGraph(int M, int N) { int data, i; Vertex V, W; WeightType Weight; MGraph Graph; Graph=CreateGraph(M); Graph->Ne=N; for(V=0; V<Graph->Nv; V++) { scanf("%d", &data); Graph->Data[V]=data; } for(i=0; i<Graph->Ne; i++) { scanf("%d %d %d", &V, &W, &Weight); /* 插入邊 */ Graph->G[V][W]=Weight; Graph->G[W][V]=Weight; } return Graph; } void Dijkstra_X(MGraph Graph, int path[], int dist[], Vertex S, Vertex E) /* 單源最短路徑演算法變形 */ { /* path記錄每個點的最短路徑條數,dist記錄每個點的最短路徑長度,Sum記錄每個點的最短路徑上的最大救援隊數量 */ int collected[MaxVertexNum], Sum[MaxVertexNum]; Vertex V, W; /* 初始化:此處預設鄰接矩陣中不存在的邊用INFINITY表示 */ dist[S] = 0; collected[S] = true; Sum[S]=Graph->Data[S]; for ( V=0; V<Graph->Nv; V++ ) { if(V==S) V++; dist[V] = Graph->G[S][V]; if ( dist[V]<INFINITY ) { Sum[V]=Sum[S]+Graph->Data[V]; path[V] = 1; } else /* 如果沒有路徑,賦值-1,方便檢查 */ { Sum[V]=-1; path[V] = -1; } collected[V] = false; } while (1) { /* V = 未被收錄頂點中dist最小者 */ V = FindMindist( Graph, dist, collected ); if ( V==-1 ) /* 若這樣的V不存在 */ break; /* 演算法結束 */ collected[V] = true; /* 收錄V */ for( W=0; W<Graph->Nv; W++ ) /* 對圖中的每個頂點W */ /* 若W是V的鄰接點並且未被收錄 */ if ( collected[W]==false && Graph->G[V][W]<INFINITY ) { /* 若收錄V使得dist[W]變小 */ if ( dist[V]+Graph->G[V][W] < dist[W] ) { dist[W] = dist[V]+Graph->G[V][W]; /* 更新dist[W] */ path[W] = path[V]; Sum[W]=Sum[V]+Graph->Data[W]; } else if(dist[V]+Graph->G[V][W] == dist[W]){ path[W]+=path[V]; if(Sum[V]+Graph->Data[W] > Sum[W]) Sum[W]=Sum[V]+Graph->Data[W]; } } } /* while結束*/ printf("%d %d", path[E], Sum[E]); } Vertex FindMindist(MGraph Graph, int dist[], int collected[]) { Vertex V, MinV; int MinDist; MinDist=INFINITY; for(V=0; V<Graph->Nv; V++) { if(!collected[V] && dist[V]<MinDist) { MinDist=dist[V]; MinV=V; } } if(MinDist<INFINITY) return MinV; else return -1; }
實在做太久了,這周的任務鐵定完不成。
最後是卡在了第二個測試點,這個測試點是起始點和目的點相同,輸出會比較特殊。
需要注意的是path和Sum的更新方法,不是遞加而是加上前面結點的值。
我的程式碼可能看起來比較方便,但是時間複雜度和空間複雜度就沒那麼好了,就這樣吧。