最短路变形
题意:输入n和m表示图的顶点数和边数然后下面m行给出每条边的信息(无向图)。起点是办公室编号1,终点时家编号2。从1到2,问满足要求的路径条数。要求就是,该条路径经过A点到B点的话,那么经过B点到家的最短路径值要小于A点到家的最短路径值,关于这句话是什么意思,看下面的注释
还好是1A了这题,否则的话感觉要调试很久
//先以家为源点运行一次dij得到家到每个点的最短路(也就是每个点到家的最短路) //那么从办公室到家的最短路(一条或多条)一定符合题目的要求,因为最短路本身有最优子结构的性质 //还有一些路径,不是办公室到家的最短路,但是它符合题目的要求 //例如办公室为O,家为H,从O到H的最短路中经过C,OC=2,CH=8,即OH=10 //而有另外的一个点B,B到H的最短路BH=5,但OB=6,其实B点并不属于最短路(若0经过B到H长度为11) //但是BH=5<OH=10,符合题目的意思 //所以我们知道,答案一定大于等于OH最短路的条数 //统计路径的数目用DFS记忆化搜索实现 //c[i]表示i这个点到终点H的路径条数 //c[i]=c[x1]+c[x2]+c[x3]……c[xm],其中x点与i点相连,并且x点最短路值小于i点最短路值 //邻接表建图 //DIJ一遍 //DFS记忆化搜索统计路径数 #include <cstdio> #include <cstring> #define N 1050 #define M 2000050 #define INF 0x3f3f3f3f struct edge { int u,v,w,next;}e[M]; int first[N]; int n,en; int d[N]; bool used[N]; int c[N]; void dfs(int u) { if(c[u]!=-1) return ; c[u]=0; for(int i=first[u]; i!=-1; i=e[i].next) { int v=e[i].v; if(d[v] < d[u]) { dfs(v); c[u]+=c[v]; } } } void solve(int s ,int t) { memset(c,-1,sizeof(c)); c[t]=1; dfs(s); printf("%d\n",c[s]); } void DIJ(int s) { memset(d,0x3f,sizeof(d)); memset(used,0,sizeof(used)); d[s]=0; for(int nn=1; nn<n-1; nn++) { int min=INF,k=s; for(int i=1; i<=n; i++) if(d[i]<min && !used[i]) { min=d[i]; k=i;} used[k]=1; for(int i=first[k]; i!=-1; i=e[i].next) //邻接表松弛 { int v=e[i].v , w=e[i].w; if(w+d[k] < d[v]) d[v]=d[k]+w; } } } void add(int u ,int v ,int w) { e[en].u=u; e[en].v=v; e[en].w=w; e[en].next=first[u]; first[u]=en++; } void build() { int m; memset(first,-1,sizeof(first)); en=0; scanf("%d",&m); for(int i=1; i<=m; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } } int main() { while(scanf("%d",&n)!=EOF && n) { build(); DIJ(2); solve(1,2); } return 0; }