http://pat.zju.edu.cn/contests/pat-a-practise/1003
题意是要求单源点对最短路径数和最大的点权重之和。
(1)首先要用dijstra算法,求出最短路径长度。
(2)为了求最短路径数,还得用深搜(dfs),依次把点加入集合中,若路径长度=最短路径值时,路径数+1。同时求出最大的点权重之和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #include<stdio.h> #include<vector> using namespace std; struct E{ int next; int c; }; vector<E> edge[510]; bool visit[510]; int dis[510]; int num[510];//记录救援队的数目 int n,m,c1,c2; int sum;//用于记录路径的数目 int team;//记录小分队的数目 int dij(int start){ //计算单源路径 int i,j; for(i=0;i<n;++i){ visit[i]=false; dis[i]=-1; } int newp=start; visit[newp]=true; dis[newp]=0; for(i=1;i<n;++i){ for(j=0;j<edge[newp].size();++j){ int t=edge[newp][j].next; int c=edge[newp][j].c; if(visit[t]==true) continue; if(dis[t]==-1 || dis[t]>dis[newp]+c) dis[t]=dis[newp]+c; } int min=123123123; for(j=0;j<n;++j){ if(visit[j]==true) continue; if(dis[j]==-1) continue; if(dis[j]<min){ min=dis[j]; newp=j; } } visit[newp]=true; } return dis[c2]; } void dfs(int root,int distance,int teamnum){ //dfs回溯,求最短路径的数目 int j; if(root==c2){//如果遍历到终点 if(distance==dis[c2]){ sum++; //记录数目 if(teamnum>team) team=teamnum; } return; } if(distance>dis[c2]) //遍历路径比最小路径长,直接返回 return; for(j=0;j<edge[root].size();++j){ if(visit[edge[root][j].next]==true) continue; visit[edge[root][j].next]=true; dfs(edge[root][j].next,distance+edge[root][j].c,teamnum+num[edge[root][j].next]); visit[edge[root][j].next]=false; //回溯 } } int main(){ int i,j; int x,y,z; E tmp; scanf("%d %d %d %d",&n,&m,&c1,&c2); for(i=0;i<n;++i){ scanf("%d",&num[i]); } while(m--){ scanf("%d %d %d",&x,&y,&z); tmp.next=y; tmp.c=z; edge[x].push_back(tmp); tmp.next=x; edge[y].push_back(tmp); } int distance=dij(c1); //printf("distance=%d\n",distance); for(i=0;i<n;++i){ visit[i]=false; } sum=0; team=0; dfs(c1,0,num[c1]); printf("%d %d\n",sum,team); return 0; } |