变形最短路 SCU 4444 training 3

来源:互联网 发布:国家数据恢复中心费用 编辑:程序博客网 时间:2024/05/11 09:01
  1. 题意转自http://blog.csdn.net/lvshubao1314/article/details/48848319
  2. SCU - 4444 别样最短路径-大数据完全图 
  3. 题目大意:给定一个完全图,其中有两种边,长度为a(不超过5e5)或长度为b(剩下的),求有1~n的最短路径(数据范围1e5) 
  4. 解题思路:如果1和n之间连边为a那么答案一定为a和一条最短的全由b组成的路径的较小者,如果1和n之间连边为b,那么答案一定 
  5.            为b和一条最短的全由a组成的路径的较小者。对于第1种情况直接跑spfa就可以了,第二种情况由于边数较多,不能直接spfa 
  6.            从1开始搜索与其相连的边权为b的边,用set维护一下,由于每个点只入队1次,复杂度还是允许的。这种处理方法还是第一 
  7.            次做,感觉很巧妙 

分析:  自己比赛的时候也大概想到了对于公路的讨论,,但是不会表示。也感觉太复杂了,,

在bfs中
其实这个地方的set就相当于vis数组一样,,但是如果用vis的话,我就要从1~n遍历,显然会超时,所以用set  ,这样遍历就不用扫那么多点。。。(也许这只是套路,学会就行)

#include<bits/stdc++.h>#define ll long long#define sf scanf#define mem(a,b) memset(a,b,sizeof(a));using namespace std;const long long INF=1e17;int n,m;ll a,b;const int maxn=5*1e5+5;ll d[maxn];set<int>st,ts;set<int>::iterator it;struct Edge{    int v,nxt;}edge[maxn*2];int tol;int vis[maxn];int head[maxn];void addedge(int u,int v){    edge[tol].v=v;edge[tol].nxt=head[u];    head[u]=tol++;}void init(){    tol=0;    mem(vis,0);    mem(head,-1);}void bfs(){    queue<int>q;st.clear();ts.clear();    q.push(1);    for(int i=2;i<=n;++i){        d[i]=INF;        st.insert(i);    }    while(!q.empty()){        int u=q.front();q.pop();        for(int i=head[u];~i;i=edge[i].nxt){            int v=edge[i].v;            if(st.count(v)==0)continue;            st.erase(v);ts.insert(v);        }        for(it=st.begin();it!=st.end();it++){            q.push(*it);            d[*it]=d[u]+1;        }        st.swap(ts);//其实st和 ts就相当于 vis的作用,用来标记哪些点有没走过        ts.clear();    }    printf("%lld\n",min(d[n]*b,a));}void spfa(){    mem(vis,0);    queue<int>q;    q.push(1);    vis[1]=1;    d[1]=0;    for(int i=2;i<=n;++i)d[i]=INF;    while(!q.empty()){        int u=q.front();q.pop();        vis[u]=0;        for(int i=head[u];i!=-1;i=edge[i].nxt){            int v=edge[i].v;            if(d[v]>d[u]+1){                d[v]=d[u]+1;                if(!vis[v]){                    vis[v]=1;                    q.push(v);                }            }        }    }    printf("%lld\n",min(d[n]*a,b));}int main(){    while(~scanf("%d%d%d%d",&n,&m,&a,&b)){        init();        int fg=0;        for(int i=1;i<=m;++i){            int u,v;            scanf("%d%d",&u,&v);            addedge(u,v);            addedge(v,u);            if(u==1&&v==n||u==n&&v==1)fg=1;        }        if(fg)bfs();        else spfa();    }}


0 0