题意:n个点,n-1条边,组成一个无向的联通图,然后给出q和k,q次询问,每次给出两个点,问这两个点之间的最短距离但必须经过k点。
思路:我当时是用优化的Dijkstra写的(当天刚学的),求出k点到各点的最短距离,跑了160+ms,其实用搜索写更快,组里的几个大佬都用搜索写的,我在搜索这方面还是比较弱的。还要多练练。然后今天早上用搜索写了一下,跑了60+ms,并且内存用的也很小。
题目链接:http://abc070.contest.atcoder.jp/tasks/abc070_d
Dijkstra优先队列优化代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> using namespace std; #define ll long long const ll INF=1e15+10; #define MAX 100005 typedef pair<ll,ll> p; struct Edge{ ll to; ll cost; Edge(ll to,ll cost):to(to),cost(cost){} }; vector<Edge> edge[MAX*100]; ll dis[MAX]; ll u,v,w; ll n,q,x; void Dijkstra(int s) { priority_queue<p,vector<p>,greater<p> > que; fill(dis+1,dis+n+1,INF); dis[s]=0; que.push(p(0,s)); while(!que.empty()) { p P=que.top(); que.pop(); v=P.second; if(dis[v]<P.first) continue; for(ll i=0;i<edge[v].size();i++) { Edge e=edge[v][i]; if(dis[e.to]>dis[v]+e.cost) { dis[e.to]=dis[v]+e.cost; que.push(p(dis[e.to],e.to)); } } } } int main() { scanf("%lld",&n); for(ll i=1;i<=n-1;i++) { scanf("%lld%lld%lld",&u,&v,&w); edge[u].push_back(Edge(v,w)); edge[v].push_back(Edge(u,w)); } scanf("%lld%lld",&q,&x); Dijkstra(x); for(int i=0;i<q;i++) { scanf("%lld%lld",&u,&v); printf("%lld\n",dis[u]+dis[v]); } return 0; }
DFS搜索:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAX 100005 #define ll long long struct Edge{ ll to; ll next; ll cost; }; Edge edge[MAX*2]; ll head[MAX]; ll dis[MAX]; void DFS(ll u,ll v,ll w) { dis[u]=w; for(ll i=head[u];i!=-1;i=edge[i].next) { ll to=edge[i].to; if(to==v) continue; DFS(to,u,w+edge[i].cost); } return ; } int main() { ll n,u,v,w,q,k; scanf("%lld",&n); ll cnt=0; memset(head,-1,sizeof(head)); for(ll i=1;i<=n-1;i++) { scanf("%lld%lld%lld",&u,&v,&w); edge[cnt].to=v; edge[cnt].cost=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].to=u; edge[cnt].cost=w; edge[cnt].next=head[v]; head[v]=cnt++; } scanf("%lld%lld",&q,&k); DFS(k,-1,0); while(q--) { scanf("%lld%lld",&u,&v); printf("%lld\n",dis[u]+dis[v]); } return 0; }