您的位置:首页 > 其它

ZOJ 2864 多条最短路径

2011-04-01 20:55 267 查看
好吧, 终于可以缓解下这两天的想砍人的情绪了。开始错了之后就跟别人讨论——以为是数据变态(后来某某学长的一句话更是令我们崩溃):这个小偷能 瞬间移动 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]是解决不了问题的。

②这是求多条最短路径,长见识了。

③还是该干嘛干嘛,偷懒的代价很严重。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: