博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

[JZOJ 5818] 做运动

题意:带温度最短路。
思路:
我们将温度从小到大的将边加入,用并查集维护连通性。
如果一旦联通那么跑一遍\(spfa\)就可以得到答案。
复杂度\(O(m log m)\)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e6 + 10;
inline int read () {
	int q=0,f=1;char ch = getchar();
	while(!isdigit(ch)) {
		if(ch=='-')f=-1;ch=getchar();
	}
	while(isdigit(ch)){
		q=q*10+ch-'0';ch=getchar();
	}
	return q*f;
}
int n,m,S,T;
bool vis[maxn];
ll dis[maxn];
int f[maxn];
int ans;
int siz[maxn];
struct edge {
	int u;
	int v;
	int w;
	int t;
}e[maxn << 1];
queue<int>q;
inline bool cmp(edge x,edge y) {
	return x.w < y.w;
}
int get(edge p,int k) {
	if(k == p.u) return p.v;
	return p.u;
}
inline int find (int x) {
	return x == f[x] ? x : f[x] = find(f[x]);
}
vector<edge>v[maxn];
inline void spfa(int s) {
	memset(dis,-1,sizeof(dis));
	memset(vis,false,sizeof(vis));
	dis[s] = 0;
	vis[s] = 1;
	q.push(s);
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		vis[u] = 0;
		for(int i = 0;i < v[u].size(); ++i) {
			int y = get(v[u][i],u);
			if(v[u][i].w > ans) continue;
			if(dis[y] == -1 || dis[y] > dis[u] + (ll)v[u][i].w * v[u][i].t) {
				dis[y] = dis[u] + (ll)v[u][i].w * v[u][i].t;
				if(!vis[y]) {
					q.push(y);
					vis[y] = 1;
				}
			}
		}
	}
}
#define pb(x) push_back(x)
int main () {
	freopen("running.in","r",stdin);
	freopen("running.out","w",stdout);
	n = read(),m = read();
	for(int i = 1;i <= n; ++i) {
		f[i] = i;
		siz[i] = 1;
	}
	for(int i = 1;i <= m; ++i) {
		e[i].u = read(),e[i].v = read(),e[i].w = read(),e[i].t = read();
		v[e[i].u].pb(e[i]);
		v[e[i].v].pb(e[i]);
	}
	S = read(),T = read();
	sort(e + 1,e + m + 1,cmp);
	for(int i = 1;i <= m; ++i) {
		int x = e[i].u;
		int y = e[i].v;
		int l = find(x);
		int r = find(y);
		if(l != r) f[l] = r;
		if(find(S) == find(T)) {
			ans = e[i].w;
			break;
		}
	}
	spfa(S);
	printf("%d %lld",ans,dis[T]);
	return 0;
}
posted @ 2018-09-06 10:03  Allorkiya  阅读(131)  评论(0编辑  收藏  举报