[NOIP模拟][并查集][最短路]做运动

样例输入:

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+队列优化),以为大概能过,实际上只有70分。
分析:正解的话就是把边按照温度排序,从小到大,一条边一条边加,直到起点和终点联通(用并查集实现),这时这条边的温度就是欲求的答案,再把所有小于这个温度的边建图作一遍最短路,就得到答案。
PS:这道题卡常啊,SPFA会被卡。要用dijkstra+队列(堆)优化,然后再加些inline,register,才能勉强过。
附代码:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<algorithm>
#include<queue>
using namespace std;

const int N=5e5+100;
const int M=1e6+100;
const long long INF=1e18;
int n,m,tot,nxt[M*2],to[M*2],first[N],ss,tt,ans,fa[N],fta,ftb,po;
long long w[M*2],dis[N];
priority_queue<pair<long long,int > >q;
struct node{
    int x,y,t;
    long long w;
}bian[M];

inline int readint()
{
    char ch;int i=0,f=1;
    for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    if(ch=='-') {ch=getchar();f=-1;}
    for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';
    return i*f;
}

inline void create(int a,int b,long long d)
{
    tot++;
    nxt[tot]=first[a];
    first[a]=tot;
    to[tot]=b;
    w[tot]=d;
}

inline bool comp(const node &a,const node &b)
{
    return a.t<b.t;
}

inline int getfa(int x)
{
    if(fa[x]==x) return x;
    return fa[x]=getfa(fa[x]);
}

inline void dijkstar(int maxt)
{
    for(register int i=1;i<=n;i++) dis[i]=INF;
    dis[ss]=0;
    q.push(make_pair(0,ss));
    while(!q.empty())
    {
        int u=q.top().second;
        q.pop();
        if(u==tt) break;
        for(register int e=first[u];e;e=nxt[e])
        {
            int v=to[e];
            if(dis[u]+w[e]<dis[v])
            {
                dis[v]=dis[u]+w[e];
                q.push(make_pair(-dis[v],v));
            }
        }
    }
}

int main()
{
    //freopen("running.in","r",stdin);
    //freopen("running.out","w",stdout);

    int t,x,y;long long c;
    n=readint();m=readint();
    for(register int i=1;i<=m;i++)
    {
        bian[i].x=readint();bian[i].y=readint();t=readint();c=readint();
        bian[i].t=t;bian[i].w=t*c;
    }
    ss=readint();tt=readint();
    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;
        fta=getfa(x);
        ftb=getfa(y);
        create(x,y,bian[i].w);
        create(y,x,bian[i].w);
        if(fta!=ftb)
        {
            fa[fta]=ftb;
            if(getfa(ss)==getfa(tt))
            {
                ans=bian[i].t;
                po=i;
                break;
            }
        }
    }
    for(register int i=po+1;i<=m;i++)
    {
        if(bian[i].t>ans) break;
        create(bian[i].x,bian[i].y,bian[i].w);
        create(bian[i].y,bian[i].x,bian[i].w);
    }
    dijkstar(ans);
    cout<<ans<<" "<<dis[tt];

    return 0;
}
发布了99 篇原创文章 · 获赞 8 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qianguch/article/details/78357983