P1119 灾后重建

灾后重建


方法

  • Floyd
  • 邻接矩阵存图
  • 对于每次查询不下降的t,用新重建好的村庄k更新其他村庄
  • 判断查询的x村庄和y村庄是否重建好
    • 重建好并且有路连通则输出G[x][y]
    • 没重建好或者重建好没路连通,输出-1

此方法模拟细节

  • 首先,边是在邻接矩阵里,不管重没重建好都在里面
  • k村庄重建好后立即更新通过k村庄的路
  • 当x村庄和y村庄都重建好了,并且之间有路或者能通过之前的k村庄到达
  • 那么就有答案

80分Dijkstra代码

#include <bits/stdc++.h>

#define pr pair<int, int>
#define mk make_pair

using namespace std;

const int N = 201;

struct Edge_{
	int u, v, w;
	int maxt;
}E[N * 50 * 2];

struct Edge{
	int v,w,nxt;
}edge[N * 50 * 2];

int n,m,p = 1,top,Q;
int T[N],head[N],dist[N];

bool cmp(Edge_ a, Edge_ b){return a.maxt < b.maxt;}

inline void addedge(int u, int v, int w){
	edge[++top].v = v;
	edge[top].w = w;
	edge[top].nxt = head[u];
	head[u] = top;
}

inline void check(int t){
	while(p <= m && E[p].maxt <= t){
		addedge(E[p].u, E[p].v, E[p].w);
		addedge(E[p].v, E[p].u, E[p].w);
		++p;
	}
}

priority_queue<pr, vector<pr>, greater<pr> >q;
inline void Dijkstra(int s){
	for(register int i = 1; i <= n; ++i) dist[i] = 1e9;
	dist[s] = 0;
	q.push(mk(dist[s], s));
	while(!q.empty()){
		int u = q.top().second;
		int d = q.top().first; q.pop();
		if(d > dist[u]) continue;
		for(register int i = head[u]; i; i = edge[i].nxt){
			int v = edge[i].v;
			int w = edge[i].w;
			if(dist[u] + w < dist[v]){
				dist[v] = dist[u] + w;
				q.push(mk(dist[v], v));
			}
		}
	}
}

/*
+ 把边加入一个集合
+ 按照边与边两个端点的最大重建时间之间的最小值为第一优先级排序
+ 读入查询次数
+ 对每个新t进行判断
+ 如果p < n && 还未加边的maxt < 新t,就加入这条边 
+ Dijkstra() 
*/

int rd();
int main(){
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout); 
	n = rd(), m = rd();
	for(register int i = 1; i <= n; ++i) T[i] = rd();
	for(register int i = 1; i <= m; ++i){
		E[i].u = rd() + 1, E[i].v = rd() + 1, E[i].w = rd();
		E[i].maxt = max(T[E[i].u], T[E[i].v]);
	}
	sort(E + 1, E + m + 1, cmp);
	Q = rd(); 
	for(register int i = 1, x, y, t; i <= Q; ++i){
		x = rd() + 1, y = rd() + 1, t = rd();
		check(t);
		if(t < max(T[x], T[y])){printf("-1\n"); continue;} //如果仍有村庄未重建完,那么是没有路进去也没有路出来的 
		Dijkstra(x);
		dist[y] == 1e9 ? printf("-1\n") : printf("%d\n", dist[y]);
	}
	return 0;
}

int rd(){
	int X = 0, flag = 1;
	char ch = getchar();
	while(!isdigit(ch)) flag = ch == '-' ?  -1 : 1, ch = getchar();
	while(isdigit(ch)) X = X * 10 + ch - 48, ch = getchar();
	return X * flag; 
}

100分Floyd代码

#include <bits/stdc++.h>

using namespace std;

const int N = 200;

int n,m,Q;
int T[N],G[N][N];

void Floyd(int k){
	for(int u = 0; u < n; ++u){
		for(int v = 0; v < n; ++v){				
			if(G[u][k] + G[k][v] < G[u][v]){
				G[u][v] = G[v][u] = G[u][k] + G[k][v]; 
			}				
		}
	}	
}

int main(){
	cin >> n >> m;
	for(int u = 0; u < n; ++u)
		for(int v = 0; v < n; ++v)
			G[u][v] = 0x3fffffff;
	for(int u = 0; u < n; ++u) 
		G[u][u] = 0;
	for(int i = 0; i < n; ++i) cin >> T[i];
	for(int i = 0, u, v, w; i < m; ++i){
		cin >> u >> v >> w;
		G[u][v] = G[v][u] = w;
	}
	cin >> Q;
	int k = 0;
	for(int i = 0, x, y, t; i < Q; ++i){
		cin >> x >> y >> t;
		while(T[k] <= t && k < n){
			Floyd(k);
			++k;
		}
		if(T[x] > t || T[y] 
		> t || G[x][y] == 0x3fffffff) cout << -1 << endl;		
		else cout << G[x][y] << endl;		
	}
	return 0;
}
posted @ 2019-07-31 20:48  探险家_H  阅读(139)  评论(0编辑  收藏  举报