题意:一个人从A到B,只能走这样的边回家,起点到B的距离比终点到B的距离更短,问有几条路径能回家
题解:水题,先从B开始来一遍dijstra,得到所有的满足条件的边,就是一个DAG,记忆化搜索+DP就可以
#include <bits/stdc++.h> #define ll long long #define maxn 100010 #define INF 1e9+7 using namespace std; struct edge{ int from,to,dist; }; struct node{ int d,u; bool operator<(const node& a) const{ return d>a.d; } }; struct dij{ int n,m; vector<int >G[maxn];//从0开始 vector<edge>edges; bool done[maxn]; int d[maxn]; //距离 int p[maxn]; //上一条边,端点判断 void init(int x){//边数,初始化 n = x; for(int i=0;i<n;i++) G[i].clear(); edges.clear(); } void add(int a,int b,int w){ edges.push_back((edge){a,b,w}); m = edges.size(); G[a].push_back(m-1); } void dijstra(int st){//计算最短路 for(int i=0;i<n;i++) d[i] = INF; memset(done, 0, sizeof(done)); d[st] = 0; priority_queue<node>q; q.push((node){0, st}); while(!q.empty()){ node fi = q.top();q.pop(); int u = fi.u; if(done[u]) continue; done[u] = 1; for(int i=0;i<G[u].size();i++){ edge& e = edges[G[u][i]]; if(e.dist+d[u]<d[e.to]){ d[e.to] = d[u]+e.dist; p[e.to] = G[u][i]; q.push((node){d[e.to], e.to}); } } } } }ds, de; int s,e; void dfs1(int a){ if(a == s){ cout<<a+1; return ; } edge e = ds.edges[ds.p[a]]; dfs1(e.from); cout<<" "<<a+1; } void dfs2(int a){ if(a == e){ cout<<" "<<a+1; return ; } edge e = de.edges[de.p[a]]; cout<<" "<<a+1; dfs2(e.from); } int main(){ int n, m, k, a, b, c, aaa=0; while(cin>>n>>s>>e){ if(aaa++) cout<<"\n"; s--,e--; ds.init(n);de.init(n); cin>>m; for(int i=0;i<m;i++){ cin>>a>>b>>c; a--,b--; ds.add(a, b, c);ds.add(b, a, c); de.add(a, b, c);de.add(b, a, c); } ds.dijstra(s); de.dijstra(e); cin>>k; int u=-1,v=-1, ans = ds.d[e]; for(int i=0;i<k;i++){ cin>>a>>b>>c; a--,b--; if(ds.d[a]+c+de.d[b] < ans){ ans = ds.d[a]+c+de.d[b]; u = a; v = b; } if(ds.d[b]+c+de.d[a] < ans){ ans = ds.d[b]+c+de.d[a]; u = b; v = a; } } if(u == -1){ dfs1(e);cout<<endl; cout<<"Ticket Not Used\n"; cout<<ans<<endl; } else{ dfs1(u);dfs2(v);cout<<endl; cout<<u+1<<"\n"<<ans<<endl; } } //fclose(stdout); return 0; }
时间: 2024-10-08 01:42:08