Time Limit: 2000MS | Memory Limit: 30000KB | 64bit IO Format: %I64d & %I64u |
Description
Input
Output
Sample Input
7 6 1 6 13 E 6 3 9 E 3 5 7 S 4 1 3 N 2 4 20 W 4 7 2 S 3 1 6 1 4 2 6
Sample Output
13 3 36
题意:在一棵树上,查询(u,v)最短距离。
分析:LCA+tarjan离线算法,模板题。
ps:最近写LCA用的都是数组来存边,感觉比vector好用多了~~~~~
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11131
代码清单:
//#pragma comment(linker, "/STACK:102400000,102400000") #include<set> #include<map> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<string> #include<cstdio> #include<cstring> #include<cctype> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; const int maxn = 40000 + 5; const int maxv = 40000 + 5; const int maxq = 10000 + 5; struct MAX{ int v,d; MAX(){} MAX(int v,int d){ this -> v = v; this -> d = d; } }; struct Q{ int v,id,next; }quary[2*maxq]; struct e{ int v,dis,next; }graph[2*maxn]; int n,m,q; int a,b,c; char s[3]; int father[maxn]; bool vis[maxn]; int ans[maxq]; int color[maxn]; int depth[maxn]; int nume,numq; int heade[maxn]; int headq[maxn]; void init(){ for(int i=1;i<=maxn;i++) father[i]=i; memset(ans,-1,sizeof(ans)); memset(color,0,sizeof(color)); memset(depth,0,sizeof(depth)); memset(vis,false,sizeof(vis)); memset(graph,0,sizeof(graph)); memset(quary,0,sizeof(quary)); memset(heade,-1,sizeof(heade)); memset(headq,-1,sizeof(headq)); nume=numq=0; } void add_E(int u,int v,int dis){ graph[nume].v=v; graph[nume].dis=dis; graph[nume].next=heade[u]; heade[u]=nume++; } void add_Q(int u,int v,int id){ quary[numq].v=v; quary[numq].id=id; quary[numq].next=headq[u]; headq[u]=numq++; } void input(){ for(int i=0;i<m;i++){ scanf("%d%d%d%s",&a,&b,&c,s); add_E(a,b,c); add_E(b,a,c); } scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d",&a,&b); add_Q(a,b,i); add_Q(b,a,i); } } int Find(int x){ return x!=father[x] ? father[x]=Find(father[x]) : father[x]; } void tarjan(int u){ color[u]=1; vis[u]=true; for(int i=headq[u];i!=-1;i=quary[i].next){ int ID=quary[i].id; if(ans[ID]!=-1) continue; int v=quary[i].v; if(color[v]==0) continue; if(color[v]==1) ans[ID]=depth[u]-depth[v]; if(color[v]==2) ans[ID]=depth[u]+depth[v]-2*depth[Find(v)]; } for(int i=heade[u];i!=-1;i=graph[i].next){ int vv=graph[i].v; int dis=graph[i].dis; if(!vis[vv]){ depth[vv]=depth[u]+dis; tarjan(vv); color[vv]=2; father[vv]=u; } } } void solve(){ tarjan(1); for(int i=1;i<=q;i++){ printf("%d\n",ans[i]); } } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ init(); input(); solve(); } return 0; }