2、做运动 5109
(sport)
【问题描述】
一天,Y君在测量体重的时候惊讶的发现,由于常年坐在电脑前认真学习,她的体重有了突飞猛进的增长。
幸好Y君现在退役了,她有大量的时间来做运动,她决定每天从教学楼跑到食堂来减肥。
Y君将学校中的所有地点编号为1到n,其中她的教学楼被编号为S,她的食堂被编号为T,学校中有m条连接两个点的双向道路,保证从任意一个点可以通过道路到达学校中的所有点。
然而Y君不得不面临一个严峻的问题,就是天气十分炎热,如果Y君太热了,她就会中暑。
于是Y君调查了学校中每条路的温度t,及通过一条路所需的时间c。Y君在温度为t的地方跑单位时间,就会使她的热量增加t。
由于热量过高Y君就会中暑,而且Y君也希望在温度较低的路上跑,她希望在经过的所有道路中最高温度最低的前提下,使她到达食堂时的热量最低 (从教学楼出发时,Y君的热量为0)。
请你帮助Y君设计从教学楼到食堂的路线,以满足她的要求。你只需输出你设计的路线中所有道路的最高温度和Y君到达食堂时的热量。
【输入格式】
第一行由一个空格隔开的两个正整数n,m,代表学校中的地点数和道路数。
接下来m行,每行由一个空格隔开的四个整数a,b,t,c 分别代表双向道路的两个端点,温度和通过所需时间。
最后一行由一个空格隔开的两个正整数S,T,代表教学楼和食堂的编号。
注意:输入数据量巨大,请使用快速的读入方式。
【输出格式】
输出一行由一个空格隔开的两个整数,分别代表最高温度和热量。
【输入样例】
5 6
1 2 12
2 32 2
34 3 4
4 5 3 5
1 3 4 1
3 5 3 6
1 5
【输出样例】
3 24
【数据规模与约定】
10%的数据满足t=0
另外10%的数据满足c=0
另外30%的数据满足n≤2000
100%的数据满足n≤500000,m≤1000000,0≤t≤10000,0≤c≤10^8,1≤a,b,S,T≤n,S≠T
考虑将所有边按温度从小到大排序加入图中,同时用并查集维护 S 和 T 的连通性。
如果加入某些边之后 S 和 T 联通了,那么跑一遍 S 到 T 的最短路即可得到答案。
注意温度相等的边要一起加入图中。
时间复杂度 O(mlogm)
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #include<algorithm> 6 #define N 7000005 7 typedef long long LL; 8 using namespace std; 9 struct node { 10 int u,v; 11 int c,t; 12 LL w; 13 } e[N],t[N]; 14 int first[N],nxt[N],cnt; 15 void add(int u,int v,long long c,long long t) { 16 e[++cnt].u=u; 17 e[cnt].v=v; 18 e[cnt].w=c*t; 19 nxt[cnt]=first[u]; 20 first[u]=cnt; 21 } 22 int fa[N]; 23 long long find(long long x) { 24 if(x!=fa[x])return fa[x]=find(fa[x]); 25 return fa[x]; 26 } 27 void merge(long long x,long long y) { 28 long long f1=find(x),f2=find(y); 29 if(f1!=f2) { 30 fa[f1]=f2; 31 } 32 } 33 bool cmp(node a,node b) { 34 if(a.t==b.t)return a.c<b.c; 35 return a.t<b.t; 36 } 37 long long n,m; 38 int S,T; 39 int max0=0; 40 void kruskal() { 41 int cnt_=0; 42 for(int i=1; i<=m; i++) { 43 int u=t[i].u,v=t[i].v; 44 if(find(S)!=find(T)) { 45 merge(u,v); 46 add(u,v,t[i].c,t[i].t); 47 add(v,u,t[i].c,t[i].t); 48 max0=max(max0,t[i].t); 49 if(find(S)==find(T)){ 50 int now=i+1; 51 while(t[now].t==t[i].t){ 52 add(t[now].u,t[now].v,t[now].c,t[now].t); 53 add(t[now].v,t[now].u,t[now].c,t[now].t); 54 now++; 55 } 56 break; 57 } 58 } 59 } 60 } 61 long long dis[N]; 62 int vis[N]; 63 void spfa() { 64 queue<int>q; 65 memset(dis,0x3f3f3f3f,sizeof dis); 66 memset(vis,0,sizeof vis); 67 dis[S]=0; 68 vis[S]=1; 69 q.push(S); 70 while(!q.empty()){ 71 int u=q.front(); 72 q.pop(); 73 vis[u]=0; 74 for(int i=first[u];i;i=nxt[i]){ 75 int v=e[i].v; 76 if(dis[v]>dis[u]+e[i].w){ 77 dis[v]=dis[u]+e[i].w; 78 if(!vis[v]){ 79 vis[v]=1; 80 q.push(v); 81 } 82 } 83 } 84 } 85 } 86 int read(){ 87 int x=0,f=1; 88 char c=getchar(); 89 while(!isdigit(c)){ 90 if(c=='-')f=-1; 91 c=getchar(); 92 } 93 while(isdigit(c)){ 94 x=(x<<3)+(x<<1)+c-'0'; 95 c=getchar(); 96 } 97 return x*f; 98 } 99 int main() { 100 // freopen("running1.in","r",stdin); 101 n=read(),m=read(); 102 for(int i=1; i<=n; i++)fa[i]=i; 103 for(int i=1; i<=m; i++) { 104 t[i].u=read(),t[i].v=read(),t[i].t=read(),t[i].c=read(); 105 } 106 S=read(),T=read(); 107 sort(t+1,t+m+1,cmp); 108 kruskal(); 109 spfa(); 110 cout<<max0<<" "<<dis[T]; 111 return 0; 112 }
over