//缩点+spfa /* *State: POJ3114 Accepted 2908K 375MS C++ 2953B *题目大意: * 给定一个有向有权图,然后要求求出图中任意两点间的最短距离。 * 注意图中可能有环,每一个环中的任意两点间的距离为0. *解题思路: * 题意看了好久,一开始还以为是lca,后来才发现那个奇怪的特征, * 原来每个环中的任意两点间的距离为0,就说明要进行缩点了。缩点 * 之后还是要求最短距离,这个时候就想到了spfa. * 总结就是: 缩点 + spfa *解题感想: * 从lca到缩点+spfa,感觉用缩点+spfa比较靠谱,但是估量了下,代码 * 长度可能要200行上下,不过还是稳稳地打了出来,之后经历了两次RE. * 表示这么长的代码交出了RE是一件非常恐怖的事情。但好在代码里面,我 * 自己给自己留了条路,数组的初始值能赋值为-1的都赋值为-1,经过这条 * 后路查出了是我的tarjan_scc里面一个判断条件,判断son判断成了n. * 就是缩点缩错了。最终2RE+1wa来到了最后的ac.泪奔~搞了两个钟。 */
View Code
1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <queue> 5 #include <utility> 6 #include <stack> 7 using namespace std; 8 9 const int MAXN = 505; 10 const int inf = 0x3f3f3f3f; 11 12 typedef struct _node 13 { 14 int v, w; 15 }N; 16 17 vector<N> vec[MAXN]; 18 stack<int> S; 19 int scc, dfn[MAXN], low[MAXN], step; 20 int inS[MAXN], id[MAXN]; 21 22 //spfa 23 vector<N> sccvec[MAXN]; 24 25 void deal_spfa(int n) 26 { 27 N tmp; 28 int u, v; 29 for(int i = 1; i <= n; i++) 30 { 31 for(unsigned j = 0; j < vec[i].size(); j++) 32 { 33 u = i, v = vec[i][j].v; 34 if(id[u] == id[v]) 35 continue; 36 else 37 { 38 tmp.v = id[v]; 39 tmp.w = vec[i][j].w; 40 sccvec[id[u]].push_back(tmp); 41 } 42 } 43 } 44 } 45 46 int spfa(int s, int e) 47 { 48 queue<int> Q; 49 int dis[MAXN], in[MAXN] = {0}; 50 for(int i = 0; i < MAXN; i++) 51 dis[i] = inf; 52 dis[s] = 0; 53 in[s] = 1; 54 Q.push(s); 55 while(!Q.empty()) 56 { 57 int pre = Q.front(); 58 Q.pop(); 59 in[pre] = 0; 60 for(unsigned i = 0; i < sccvec[pre].size(); i++) 61 { 62 int son = sccvec[pre][i].v; 63 int w = sccvec[pre][i].w; 64 if(dis[son] > dis[pre] + w) 65 { 66 dis[son] = dis[pre] + w; 67 if(in[son] == 0) 68 { 69 Q.push(son); 70 in[son] = 1; 71 } 72 } 73 } 74 } 75 76 return dis[e]; 77 } 78 79 void init() 80 { 81 while(!S.empty()) 82 S.pop(); 83 step = 0; 84 scc = 1; 85 for(int i = 0; i < MAXN; i++) 86 { 87 sccvec[i].clear(); 88 id[i] = 0; 89 inS[i] = 0; 90 dfn[i] = low[i] = -1; 91 vec[i].clear(); 92 } 93 } 94 95 void addEdge(int u, int v, int w) 96 { 97 N tmp; 98 tmp.v = v, tmp.w = w; 99 vec[u].push_back(tmp); 100 } 101 102 void tarjan_scc(int n) 103 { 104 dfn[n] = low[n] = ++step; 105 S.push(n); 106 inS[n] = 1; 107 for(unsigned i = 0; i < vec[n].size(); i++) 108 { 109 int son = vec[n][i].v; 110 if(dfn[son] == -1) 111 { 112 tarjan_scc(son); 113 low[n] = min(low[n], low[son]); 114 } 115 else if(inS[son] == 1) 116 { 117 low[n] = min(low[n], dfn[son]); 118 } 119 } 120 if(low[n] == dfn[n] && !S.empty()) 121 { 122 //cout << "--------------" << endl; 123 int tmp; 124 do 125 { 126 tmp = S.top(); 127 //cout << tmp << " "; 128 S.pop(); 129 inS[tmp] = 0; 130 id[tmp] = scc; 131 }while(!S.empty() && tmp != n); 132 //cout << endl; 133 scc++; 134 } 135 } 136 137 int main(void) 138 { 139 #ifndef ONLINE_JUDGE 140 //freopen("in.txt", "r", stdin); 141 #endif 142 //cout << inf << endl; 143 int n, m, cas_c = 0; 144 while(scanf("%d", &n), n) 145 { 146 scanf("%d", &m); 147 if(cas_c++ != 0) 148 printf("\n"); 149 int u, v, w; 150 init(); 151 for(int i = 0; i < m; i++) 152 { 153 scanf("%d %d %d", &u, &v, &w); 154 addEdge(u, v, w); 155 } 156 for(int i = 1; i <= n; i++) 157 { 158 if(dfn[i] == -1) 159 tarjan_scc(i); 160 } 161 162 //cout << "******" << endl; 163 deal_spfa(n); 164 int q; 165 scanf("%d", &q); 166 for(int i = 0; i < q; i++) 167 { 168 scanf("%d %d", &u, &v); 169 if(id[u] == id[v]) 170 printf("0\n"); 171 else 172 { 173 int ans = spfa(id[u], id[v]); 174 if(ans == inf) 175 printf("Nao e possivel entregar a carta\n"); 176 else 177 printf("%d\n", ans); 178 } 179 } 180 } 181 return 0; 182 } 183 184 185 186 第二次优化时间 187 State: POJ3114 Accepted 3904K 313MS C++ 2878B 188 #include <iostream> 189 #include <vector> 190 #include <cstdio> 191 #include <queue> 192 #include <utility> 193 #include <stack> 194 using namespace std; 195 196 const int MAXN = 505; 197 const int MAXE = 250005; 198 const int inf = 0x3f3f3f3f; 199 200 typedef struct _node 201 { 202 int v, w; 203 int next; 204 }N; 205 206 N edge[MAXE]; 207 int scc, dfn[MAXN], low[MAXN], step, myS[MAXN], top; 208 int inS[MAXN], id[MAXN], cntEdge, head[MAXN]; 209 210 //spfa 211 vector<N> sccvec[MAXN]; 212 213 void deal_spfa(int n) 214 { 215 N tmp; 216 int u, v; 217 for(int i = 1; i <= n; i++) 218 { 219 for(int j = head[i]; j != -1; j = edge[j].next) 220 { 221 u = i, v = edge[j].v; 222 if(id[u] == id[v]) 223 continue; 224 else 225 { 226 tmp.v = id[v]; 227 tmp.w = edge[j].w; 228 sccvec[id[u]].push_back(tmp); 229 } 230 } 231 } 232 } 233 234 int spfa(int s, int e) 235 { 236 queue<int> Q; 237 int dis[MAXN], in[MAXN] = {0}; 238 for(int i = 0; i < MAXN; i++) 239 dis[i] = inf; 240 dis[s] = 0; 241 in[s] = 1; 242 Q.push(s); 243 while(!Q.empty()) 244 { 245 int pre = Q.front(); 246 Q.pop(); 247 in[pre] = 0; 248 for(unsigned i = 0; i < sccvec[pre].size(); i++) 249 { 250 int son = sccvec[pre][i].v; 251 int w = sccvec[pre][i].w; 252 if(dis[son] > dis[pre] + w) 253 { 254 dis[son] = dis[pre] + w; 255 if(in[son] == 0) 256 { 257 Q.push(son); 258 in[son] = 1; 259 } 260 } 261 } 262 } 263 264 return dis[e]; 265 } 266 267 void init() 268 { 269 step = cntEdge = top = 0; 270 scc = 1; 271 for(int i = 0; i < MAXN; i++) 272 { 273 sccvec[i].clear(); 274 id[i] = 0; 275 inS[i] = 0; 276 dfn[i] = low[i] = -1; 277 head[i] = -1; 278 } 279 } 280 281 void addEdge(int u, int v, int w) 282 { 283 edge[cntEdge].v = v; 284 edge[cntEdge].w = w; 285 edge[cntEdge].next = head[u]; 286 head[u] = cntEdge++; 287 } 288 289 void tarjan_scc(int n) 290 { 291 dfn[n] = low[n] = ++step; 292 myS[top++] = n; 293 inS[n] = 1; 294 for(int f = head[n]; f != -1; f = edge[f].next) 295 { 296 int son = edge[f].v; 297 if(dfn[son] == -1) 298 { 299 tarjan_scc(son); 300 low[n] = min(low[n], low[son]); 301 } 302 else if(inS[son] == 1) 303 { 304 low[n] = min(low[n], dfn[son]); 305 } 306 } 307 if(low[n] == dfn[n] && top != 0) 308 { 309 int tmp; 310 do 311 { 312 tmp = myS[--top]; 313 inS[tmp] = 0; 314 id[tmp] = scc; 315 }while(top != 0 && tmp != n); 316 scc++; 317 } 318 } 319 320 int main(void) 321 { 322 #ifndef ONLINE_JUDGE 323 freopen("in.txt", "r", stdin); 324 #endif 325 int n, m, cas_c = 0; 326 while(scanf("%d", &n), n) 327 { 328 scanf("%d", &m); 329 if(cas_c++ != 0) 330 printf("\n"); 331 int u, v, w; 332 init(); 333 for(int i = 0; i < m; i++) 334 { 335 scanf("%d %d %d", &u, &v, &w); 336 addEdge(u, v, w); 337 } 338 for(int i = 1; i <= n; i++) 339 { 340 if(dfn[i] == -1) 341 tarjan_scc(i); 342 } 343 344 deal_spfa(n); 345 int q; 346 scanf("%d", &q); 347 for(int i = 0; i < q; i++) 348 { 349 scanf("%d %d", &u, &v); 350 if(id[u] == id[v]) 351 printf("0\n"); 352 else 353 { 354 int ans = spfa(id[u], id[v]); 355 if(ans == inf) 356 printf("Nao e possivel entregar a carta\n"); 357 else 358 printf("%d\n", ans); 359 } 360 } 361 } 362 return 0; 363 }