好吧, 终于可以缓解下这两天的想砍人的情绪了。开始错了之后就跟别人讨论——以为是数据变态(后来某某学长的一句话更是令我们崩溃):这个小偷能 瞬间移动 or 让时光倒流....(有点科幻了)。纠结了半天发先不是这个问题,因为标程都跑不出这些数据来。
最后发现是没加代码中的“红色部分”了(去掉这个,pcnt数组就乱了,除了起点之外,各个点的pcnt都会在求最短路径里被初始化):
我喜欢偷懒,喜欢用一些隐含的条件。比如初始化啦,还有这个函数递归边界啦,能不指出就不指出。
好了,于是乎。。各种悲剧。
//太恐怖了,发现之前贴上的代码求最短路径时多加了个循环 //现在改回来了,时间顿时少了400ms多。 #include <cstdio> #include <queue> #include <algorithm> using namespace std; const int INF = 10000002; const int MAXN = 1002; int g[MAXN][MAXN], vis[MAXN], dis[MAXN], isPath[MAXN], par[MAXN][MAXN], pcnt[MAXN]; typedef pair<int, int> pii; priority_queue<pii, vector<pii>, greater<pii> > q; void dijkstra(int n, int s) { fill(vis+1, vis+n+1, 0); for(int i = 1; i <= n; i++) { dis[i] = INF; } dis[s] = 0; q.push(make_pair(dis[s], s)); while(!q.empty()) { pii u = q.top(); q.pop(); int x = u.second; if(vis[x]) continue; vis[x] = 1; for(int y = 1; y <= n; y++) { if(!vis[y] && g[x][y]) { if(dis[y] > dis[x] + g[x][y]) { //除了起点外,所有的点都执行这快代码 dis[y] = dis[x]+g[x][y]; pcnt[y] = 1; par[y][0] = x; q.push(make_pair(dis[y], y)); } else if(dis[y] == dis[x] + g[x][y]){ par[y][pcnt[y]++] = x; } } } } } void buildPar(int t, int s) { isPath[t] = 1; if(t == s) { return; } for(int i = 0; i < pcnt[t]; i++) { int x = par[t][i]; if(!isPath[x]) { buildPar(x, s); } } return; } void buildRoute(int t, int s, int n) { //fill(pcnt+1, pcnt+n+1, 0); fill(isPath+1, isPath+n+1, 0); buildPar(t, s); } void query(int s, int qt, int &ans, int n) { for(int i = 1; i <= n; i++) { if(isPath[i]) { if(dis[i] == qt) { ans++; } else if(dis[i] > qt) { for(int j = 0; j < pcnt[i]; j++) { int t = par[i][j]; if(dis[t] < qt){ ans++; } } } } } } int main() { int n, m, s, t, u, v, w, q, qt, cas = 0; while(scanf("%d%d%d%d", &n, &m, &s, &t) != EOF) { if(cas) { printf("/n"); } else { cas = 1; } fill(g[1], g[n+1], 0); for(int k = 0; k < m; k++) { scanf("%d%d%d", &u, &v, &w); g[u][v] = g[v][u] = w; } dijkstra(n, s); buildRoute(t, s, n); scanf("%d", &q); for(int i = 0; i < q; i++) { scanf("%d", &qt); if(qt >= dis[t] || qt <= 0) { printf("1/n"); continue; } int ans = 0; query(s, qt, ans, n); printf("%d/n", ans); } } return 0; }
我之前以为这是无用的变态题,看来我偏激了。总结下:
①在求路径长度问题上,还是别用边的长度判断是否连通了。可能会有正的,0,或者负的情况。所以一个g[u][v]是解决不了问题的。
②这是求多条最短路径,长见识了。
③还是该干嘛干嘛,偷懒的代价很严重。