NOIP模拟:长跑路径(Dijkstra)

来源:互联网 发布:c语言入门自学书 编辑:程序博客网 时间:2024/06/01 07:37

企鹅豆豆即将要去考长跑了,但是作为一只企鹅,长跑自然比不过鸵鸟和鸡。为了公平起见,教练告诉豆豆,他可以从 K 个指定地点中选择两个不同的地点分别作为起点和终点来考试。
考试地图是一个由 N 个点 M 条边组成的没有重边和自环的连通无向图,一条边的长度为 Ai 。
豆豆想知道他的长跑考试最少需要跑多远。

即求一个图中给定点对的最近路径。

题解:
考试的时候乱搞了一个类似SPFA的做法更新每个点的最短路和次短路,感觉数据太水没把我卡掉。。

不得不说这题很妙。
按照k个点的二进制位分组,每次用该位为0的点连接新建的s点,该位为1的点连接新建的t点,跑logn次Dijkstra。时间复杂度O(nlog2n)

#include<bits/stdc++.h>using namespace std;typedef long long ll;struct IO{    streambuf *ib,*ob;    inline void init(){        ios::sync_with_stdio(false);        cin.tie(NULL);cout.tie(NULL);        ib=cin.rdbuf();ob=cout.rdbuf();    }    inline ll read(){        char ch=ib->sbumpc();ll i=0,f=1;        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}        return i*f;    }}io;const int Maxn=1e5+50;typedef pair<int,ll> pii;int n,m,k,K[Maxn];ll ans;vector<pii>edge[Maxn];int main(){    io.init();    for(int T=io.read(),tt=1;tt<=T;++tt){        n=io.read(),m=io.read();        for(int i=1;i<=n;i++)edge[i].clear();        for(int i=1;i<=m;i++){            int x=io.read(),y=io.read();            ll z=io.read();            edge[x].push_back(make_pair(y,z));            edge[y].push_back(make_pair(x,z));        }        k=io.read();        static int pos[Maxn];        memset(pos,0,sizeof(pos));        for(int i=1;i<=k;i++)K[i]=io.read(),pos[K[i]]=i;        ans=0x3f3f3f3f3f3f3f3f;        static ll dis[Maxn];        static priority_queue<pair<ll,int> >q;        for(int j=0;(1<<j)<=k;j++){            memset(dis,0x3f,sizeof(dis));            while(!q.empty())q.pop();            for(int i=1;i<=k;i++)if(i&(1<<j))dis[K[i]]=0,q.push(make_pair(0,K[i]));            while(!q.empty()){                int u=q.top().second;q.pop();                if(pos[u]&&!(pos[u]&(1<<j))){ans=min(ans,dis[u]);break;}                for(int e=edge[u].size()-1;e>=0;e--){                    int v=edge[u][e].first;ll w=edge[u][e].second;                    if(dis[v]>dis[u]+w){                        dis[v]=dis[u]+w;                        q.push(make_pair(-dis[v],v));                    }                }            }        }        cout<<ans<<endl;    }}

还有我乱搞的做法,不知道对不对。。(solve3函数里面。)

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<algorithm>#include<vector>#include<queue>using namespace std;typedef long long ll;struct IO{    streambuf *ib,*ob;    inline void init(){        ios::sync_with_stdio(false);        cin.tie(NULL);cout.tie(NULL);        ib=cin.rdbuf();ob=cout.rdbuf();    }    inline int read(){        char ch=ib->sbumpc();int i=0,f=1;        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}        while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}        return i*f;    }    inline void W(ll x){        static int buf[50];        if(!x){ob->sputc('0');return;}        if(x<0){ob->sputc('-');x=-x;}        while(x){buf[++buf[0]]=x%10;x/=10;}        while(buf[0]){ob->sputc(buf[buf[0]--]+'0');}    }}io;const ll INF=0x3f3f3f3f3f3f3f3f;const int Maxn=1e5+50;typedef pair<int,ll> pii;int T,n,m,k,K[Maxn],isk[Maxn],from1[Maxn],from2[Maxn];ll mint,dis[Maxn],dep[Maxn][2];vector<pii>edge[Maxn];inline ll dijkstra(int s){    static priority_queue<pair<ll,int> >q;    while(!q.empty())q.pop();    memset(dis,0x3f,sizeof(dis));    dis[s]=0;q.push(make_pair(0,s));    while(!q.empty()){        int u=q.top().second;q.pop();        for(int e=edge[u].size()-1;e>=0;e--){            int v=edge[u][e].first;ll w=edge[u][e].second;            if(dis[v]>dis[u]+w){                dis[v]=dis[u]+w;                q.push(make_pair(-dis[v],v));            }        }    }    ll mn=0x3f3f3f3f3f3f3f3f;    for(int i=1;i<=k;i++){        if(K[i]==s)continue;        mn=min(mn,dis[K[i]]);    }    return mn;}inline void solve1(){    mint=INF;    for(int i=1;i<=k;i++)    {mint=min(mint,dijkstra(K[i]));}    io.W(mint);io.ob->sputc('\n');}inline void dfs(int now,int f){    if(isk[now])dep[now][0]=0;    for(int e=edge[now].size()-1;e>=0;e--){        int v=edge[now][e].first;ll w=edge[now][e].second;        if(v==f)continue;        dfs(v,now);        ll dis1=w+dep[v][0],dis2=w+dep[v][1];        if(dis1<dep[now][0]){            dep[now][1]=dep[now][0];            dep[now][0]=dis1;            if(dis2<dep[now][1])dep[now][1]=dis2;        }else if(dis1<dep[now][1])dep[now][1]=dis1;    }    mint=min(mint,dep[now][0]+dep[now][1]);}inline void solve2(){    memset(dep,0x3f,sizeof(dep));    mint=INF;    dfs(1,0);    io.W(mint);io.ob->sputc('\n');}inline void upt(const pair<ll,int> p,int &from,ll &dp){    dp=p.first,from=p.second;}#include<ext/pb_ds/priority_queue.hpp>inline void solve3(){    memset(dep,0x3f,sizeof(dep));    memset(from1,0,sizeof(from1));    memset(from2,0,sizeof(from2));    mint=INF;    static  __gnu_pbds::priority_queue<pair<ll,int>,greater<pair<ll,int> >,__gnu_pbds::pairing_heap_tag>q;    static __gnu_pbds::priority_queue<pair<ll,int>,greater<pair<ll,int> >,__gnu_pbds::pairing_heap_tag>::point_iterator id[Maxn];    static int ins[Maxn];    while(!q.empty())q.pop();    for(int i=1;i<=n;i++)ins[i]=0;    for(int i=1;i<=k;i++)dep[K[i]][0]=0,id[K[i]]=q.push(make_pair(0,K[i])),ins[K[i]]=1,from1[K[i]]=K[i];    while(!q.empty()){        int u=q.top().second;q.pop();ins[u]=0;        for(int e=edge[u].size()-1;e>=0;e--){            int v=edge[u][e].first;ll w=edge[u][e].second;            static pair<ll,int> dis[5];            dis[1]=make_pair(w+dep[u][0],from1[u]);            dis[2]=make_pair(w+dep[u][1],from2[u]);            dis[3]=make_pair(dep[v][0],from1[v]);            dis[4]=make_pair(dep[v][1],from2[v]);            sort(dis+1,dis+4+1);            static pair<ll,int>distmp1,distmp2;            distmp1=dis[1];int tail=2;            while(dis[tail].second==distmp1.second)tail++;            distmp2=dis[tail];            if(distmp1==make_pair(dep[v][0],from1[v])&&distmp2==make_pair(dep[v][1],from2[v]))continue;            upt(distmp1,from1[v],dep[v][0]);upt(distmp2,from2[v],dep[v][1]);            if(ins[v])q.modify(id[v],make_pair(dep[v][0],v));            else ins[v]=1,id[v]=q.push(make_pair(dep[v][0],v));        }    }    for(int i=1;i<=n;i++)mint=min(mint,dep[i][0]+dep[i][1]);    io.W(mint);io.ob->sputc('\n');}int main(){    io.init();T=io.read();    while(T--){        n=io.read(),m=io.read();mint=INF;        for(int i=1;i<=n;i++)edge[i].clear();        memset(isk,0,sizeof(isk));        for(int i=1;i<=m;i++){            int x=io.read(),y=io.read();            ll z=io.read();            mint=min(mint,z);            edge[x].push_back(make_pair(y,z));            edge[y].push_back(make_pair(x,z));        }        k=io.read();        for(int i=1;i<=k;i++){            int x=io.read();            K[i]=x;isk[x]=1;        }        if(m==n-1)solve2();        else if(k==n){io.W(mint);io.ob->sputc('\n');}        else if(k<=4)solve1();         else  solve3();    }}