diff --git a/SCU/4444_lvshubao1314.cpp b/SCU/4444_lvshubao1314.cpp new file mode 100644 index 0000000..ee328ed --- /dev/null +++ b/SCU/4444_lvshubao1314.cpp @@ -0,0 +1,112 @@ +/** +SCU - 4444 别样最短路径-大数据完全图 +题目大意:给定一个完全图,其中有两种边,长度为a(不超过5e5)或长度为b(剩下的),求有1~n的最短路径(数据范围1e5) +解题思路:如果1和n之间连边为a那么答案一定为a和一条最短的全由b组成的路径的较小者,如果1和n之间连边为b,那么答案一定 + 为b和一条最短的全由a组成的路径的较小者。对于第1种情况直接跑spfa就可以了,第二种情况由于边数较多,不能直接spfa + 从1开始搜索与其相连的边权为b的边,用set维护一下,由于每个点只入队1次,复杂度还是允许的。这种处理方法还是第一 + 次做,感觉很巧妙 +*/ +#include +#include +#include +#include +#include +#include +using namespace std; +typedef long long LL; +const int INF=1e9+7; +const int maxn=100100; +int n,m,vis[maxn]; +LL a,b,dis[maxn]; +setst,ts; +set::iterator it; +int head[maxn],ip; +void init() +{ + memset(head,-1,sizeof(head)); + ip=0; +} +struct note +{ + int v,next; +}edge[maxn*10]; +void addedge(int u,int v) +{ + edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++; +} +void spfa() +{ + queueq; + for(int i=0;i<=n;i++)dis[i]=INF; + memset(vis,0,sizeof(vis)); + dis[1]=0; + q.push(1); + while(!q.empty()) + { + int u=q.front(); + q.pop(); + vis[u]=0; + for(int i=head[u];i!=-1;i=edge[i].next) + { + int v=edge[i].v; + if(dis[v]>dis[u]+1) + { + dis[v]=dis[u]+1; + if(!vis[v]) + { + vis[v]=1; + q.push(v); + } + } + } + } + printf("%lld\n",min(dis[n]*a,b)); +} +void bfs() +{ + dis[n]=INF; + st.clear(),ts.clear(); + for(int i=2;i<=n;i++)st.insert(i); + queueq; + q.push(1); + dis[1]=0; + while(!q.empty()) + { + int u=q.front(); + q.pop(); + for(int i=head[u];i!=-1;i=edge[i].next) + { + 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); + dis[*it]=dis[u]+1; + } + st.swap(ts); + ts.clear(); + } + printf("%lld\n",min(dis[n]*b,a)); +} +int main() +{ + while(~scanf("%d%d%lld%lld",&n,&m,&a,&b)) + { + init(); + int flag=0; + for(int i=0;iv)swap(u,v); + addedge(u,v); + addedge(v,u); + if(u==1&&v==n)flag=1; + } + if(flag)bfs(); + else spfa(); + } + return 0; +}