2017.10.26 T2 2011
样例数据
输入
5 6
1 2 1 2
2 3 2 2
3 4 3 4
4 5 3 5
1 3 4 1
3 5 3 6
1 5
输出
3 24
分析:这道题正解我在考场上直接想出:并查集+dijkstra,具体思维过程如下:
1、“以最高温度最低为前提”?怎样才能保证走的路径是最高温度最低的呢?我想到了最小生成树(是它的思想,就是并查集判断是否连通),也就是将边按照温度从小到大排序,然后从头开始连边直到s和t连通,最后一条边的温度就是最高温度的最小值(如果后面还有温度一样的也要加进来建边,因为它们也是最高温度的最小值)。
2、图建好了,“吸收的热量尽量少”,嗯,dijkstra裸题。
但是,我在用最小生成树的思想的时候,就直接按着最小生成树模板打了!本来,这道题是只要s和t还没有连通就要把前面边都加进来,但我就写成只加能更新连通性的边,这就意味着跑最短路的图就GG了。
还好,数据虽然严格,我还是能过75%的。
代码
不要问为什么长得这么怪,因为SOJ实在是卡,每次都要TLE最后两个测试点,我想了很多方法卡常,以至于搜到了一篇神犇的博客卡常数技巧
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;
inline int getint()
{
int sum=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-1;
ch=getchar();
}
for(;isdigit(ch);ch=getchar())
sum=(sum<<3)+(sum<<1)+ch-48;
return sum*f;
}
const int maxn=500010;
const int maxm=1000010;
struct node{
int x,y,t;
long long c;
}bian[maxm];
int n,m,s,tt,maxt;
int fa[maxn];
int tot,first[maxn];
struct node2{
int nxt,to;
long long w;
}lin[maxm*2];
long long dis[maxn];
priority_queue<pair<long long,int> >que;
inline int getfa(int x)
{
if(x==fa[x])
return x;
fa[x]=getfa(fa[x]);
return fa[x];
}
inline bool comp(const node &a,const node &b)
{
return a.t<b.t;
}
inline void addedge(int x,int y,long long z)
{
tot++;
lin[tot].nxt=first[x];
first[x]=tot;
lin[tot].to=y;
lin[tot].w=z;
tot++;
lin[tot].nxt=first[y];
first[y]=tot;
lin[tot].to=x;
lin[tot].w=z;
}
inline void dijkstra()
{
for(register int i=1;i<=n;++i)
dis[i]=5e17;
dis[s]=0;
que.push(make_pair(0,s));
while(!que.empty())
{
int u=que.top().second;
que.pop();
if(u==tt)
break;
for(register int p=first[u];p;p=lin[p].nxt)
{
int v=lin[p].to;
if(dis[v]>dis[u]+lin[p].w)
{
dis[v]=dis[u]+lin[p].w;
que.push(make_pair(-dis[v],v));
}
}
}
}
int main()
{
freopen("running.in","r",stdin);
freopen("running.out","w",stdout);
int x,y,t2,pos;
long long c;
n=getint(),m=getint();
for(register int i=1;i<=m;++i)
bian[i].x=getint(),bian[i].y=getint(),t2=getint(),c=getint(),bian[i].t=t2,bian[i].c=t2*c;
s=getint(),tt=getint();
sort(bian+1,bian+m+1,comp);
for(register int i=1;i<=n;++i)
fa[i]=i;
for(register int i=1;i<=m;++i)
{
x=bian[i].x,y=bian[i].y;
addedge(x,y,bian[i].c);//建边是要一直建的(我放在了if(x!=y)里orz)
x=getfa(x),y=getfa(y);
if(x!=y)
{
fa[x]=y;
x=getfa(s),y=getfa(tt);
if(x==y)
{
pos=i;
maxt=bian[i].t;
break;
}
}
}
while(bian[++pos].t==maxt)
addedge(bian[pos].x,bian[pos].y,bian[pos].c);
dijkstra();
cout<<maxt<<" "<<dis[tt]<<'\n';
return 0;
}
本题结。