10.28T1 排序+最短路

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

原文地址:https://www.cnblogs.com/saionjisekai/p/9864487.html