2014-10-26 16:17:09
思路:方向啥的不用管,直接双向边。注意,这样的构建的图是无向无根的树,我们要任选一个点做根将其转化为有根树即可,并且在DFS中不能回到父亲节点,这样就和正常的有向有根树一样了。另外这题的边是带权的,所以点的深度其实就是路径权和。
1 /************************************************************************* 2 > File Name: 1986.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 26 Oct 2014 03:30:27 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 40010; 27 28 int n,m,k; 29 int first[maxn],next[maxn << 1],ver[maxn << 1],w[maxn << 1],ecnt; 30 int vis[maxn],fa[maxn],dep[maxn]; 31 int ans[10010]; 32 vector< pair<int,int> > g[maxn]; 33 34 void Init(){ 35 memset(first,-1,sizeof(first)); 36 for(int i = 1; i <= n; ++i) 37 g[i].clear(); 38 ecnt = 0; 39 } 40 41 void Add_edge(int u,int v,int c){ 42 next[++ecnt] = first[u]; 43 ver[ecnt] = v; 44 w[ecnt] = c; 45 first[u] = ecnt; 46 } 47 48 int Find(int x){ 49 return fa[x] == x ? x : fa[x] = Find(fa[x]); 50 } 51 52 void Union(int u,int v){ 53 int x = Find(u); 54 int y = Find(v); 55 if(x != y) 56 fa[y] = x; 57 } 58 59 void Tarjan(int p,int pre,int d){ 60 dep[p] = d; 61 fa[p] = p; 62 for(int i = first[p]; i != -1; i = next[i]){ 63 int v = ver[i]; 64 if(v != pre){ 65 Tarjan(v,p,d + w[i]); 66 Union(p,v); 67 } 68 } 69 vis[p] = 1; 70 for(int i = 0; i < g[p].size(); ++i){ 71 int v = g[p][i].first; 72 if(vis[v]){ 73 int lca = Find(v); 74 int id = g[p][i].second; 75 ans[id] = dep[p] + dep[v] - 2 * dep[lca]; 76 } 77 } 78 } 79 80 int main(){ 81 char d; 82 int a,b,c; 83 scanf("%d%d",&n,&m); 84 Init(); 85 for(int i = 1; i <= m; ++i){ 86 scanf("%d %d %d %c",&a,&b,&c,&d); 87 Add_edge(a,b,c); 88 Add_edge(b,a,c); 89 } 90 scanf("%d",&k); 91 for(int i = 1; i <= k; ++i){ 92 scanf("%d%d",&a,&b); 93 g[a].push_back(MP(b,i)); 94 g[b].push_back(MP(a,i)); 95 } 96 Tarjan(1,0,0); 97 for(int i = 1; i <= k; ++i) 98 printf("%d\n",ans[i]); 99 return 0; 100 }