一道很水的黑题~~
边双缩点后用lca求树上两点间路径即可。
但是比较坑的是这道题是忽略重边的,结果我还特意考虑了重边,然后WA了几发。
还有两个点TLE了,原因是建新图的时候出现了重边。这个重边不是算法的问题,因为边双缩点后不可能有重边,而是写法上的问题:在建无向边的时候,习惯addEdge(x, y), addEdge(y, x),然而边双建边的时候两个点之间实际上连了4条边。所以写的时候只用建单向边,形成的图却是无向图。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<queue> 10 #include<stack> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const db eps = 1e-8; 19 const int INF = 0x3f3f3f3f; 20 const int maxn = 1e4 + 5; 21 const int maxe = 5e4 + 5; 22 inline ll read() 23 { 24 ll ans = 0; 25 char ch = getchar(), las = ' '; 26 while(!isdigit(ch)) las = ch, ch = getchar(); 27 while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); 28 if(las == '-') ans = -ans; 29 return ans; 30 } 31 inline void write(ll x) 32 { 33 if(x < 0) putchar('-'), x = -x; 34 if(x >= 10) write(x / 10); 35 putchar(x % 10 + '0'); 36 } 37 38 int n, m; 39 40 struct Edge 41 { 42 int nxt, to; 43 }e[maxe << 1], e2[maxe << 1]; 44 int head[maxn], ecnt = -1; 45 void addEdge(int x, int y) 46 { 47 e[++ecnt] = (Edge){head[x], y}; 48 head[x] = ecnt; 49 } 50 51 int dfn[maxn], low[maxn], cnt = 0; 52 bool in[maxn]; 53 int st[maxn], top = 0; 54 int col[maxn], ccol = 0; 55 void tarjan(int now, int f) 56 { 57 dfn[now] = low[now] = ++cnt; 58 st[++top] = now; in[now] = 1; 59 for(int i = head[now]; i != -1; i = e[i].nxt) 60 { 61 if(!dfn[e[i].to]) 62 { 63 tarjan(e[i].to, now); 64 low[now] = min(low[now], low[e[i].to]); 65 } 66 else if(e[i].to != f) low[now] = min(low[now], dfn[e[i].to]); 67 } 68 if(dfn[now] == low[now]) 69 { 70 int x; ++ccol; 71 do 72 { 73 x = st[top--]; 74 col[x] = ccol; 75 in[x] = 0; 76 }while(x != now); 77 } 78 } 79 80 int head2[maxn], ecnt2 = -1; 81 void addEdge2(int x, int y) 82 { 83 e2[++ecnt2] = (Edge){head2[x], y}; 84 head2[x] = ecnt2; 85 } 86 void newGraph(int now) 87 { 88 int u = col[now]; 89 for(int i = head[now]; i != -1; i = e[i].nxt) 90 { 91 int v = col[e[i].to]; 92 if(u == v) continue; 93 addEdge2(u, v); //addEdge2(v, u); 94 } 95 } 96 97 const int N = 20; 98 int fa[maxn][25], dep[maxn]; 99 void dfs(int now, int f) 100 { 101 for(int i = 1; i <= N; ++i) 102 fa[now][i] = fa[fa[now][i - 1]][i - 1]; 103 for(int i = head2[now]; i != -1; i = e2[i].nxt) 104 { 105 if(e2[i].to == f) continue; 106 fa[e2[i].to][0] = now; 107 dep[e2[i].to] = dep[now] + 1; 108 dfs(e2[i].to, now); 109 } 110 } 111 int lca(int x, int y) 112 { 113 if(dep[x] < dep[y]) swap(x, y); 114 for(int i = N; i >= 0; --i) 115 if(dep[x] - (1 << i) >= dep[y]) x = fa[x][i]; 116 if(x == y) return x; 117 for(int i = N; i >= 0; --i) 118 if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; 119 return fa[x][0]; 120 } 121 122 void print(int x) 123 { 124 if(!x) return; 125 print(x >> 1); 126 write(x & 1); 127 } 128 void solve(int x, int y) 129 { 130 int z = lca(x, y); 131 print(dep[x] - dep[z] + dep[y] - dep[z] + 1); 132 enter; 133 } 134 135 int main() 136 { 137 Mem(head, -1); 138 n = read(); m = read(); 139 for(int i = 1; i <= m; ++i) 140 { 141 int x = read(), y = read(); 142 addEdge(x, y); addEdge(y, x); 143 } 144 for(int i = 1; i <= n; ++i) if(!dfn[i]) tarjan(i, 0); 145 Mem(head2, -1); 146 for(int i = 1; i <= n; ++i) newGraph(i); 147 dfs(col[1], 0); 148 int q = read(); 149 for(int i = 1; i <= q; ++i) 150 { 151 int x = read(), y = read(); 152 solve(col[x], col[y]); 153 } 154 return 0; 155 }