SCU OJ_4444_ Travel_最短路(大数据)

来源:互联网 发布:c语言的广泛应用 编辑:程序博客网 时间:2024/05/22 08:39
I - Travel
Time Limit:0MS     Memory Limit:0KB     64bit IO Format:%lld & %llu
Submit Status

Description
Travel

The country frog lives in has n
towns which are conveniently numbered by 1,2,…,n

.

Among n(n?1)2
pairs of towns, m of them are connected by bidirectional(双向的) highway(公路), which needs a minutes to travel.
The other pairs are connected by railway, which needs b

minutes to travel.

Find the minimum(最小的) time to travel from town 1
to town n

.
Input

The input(投入) consists of multiple tests. For each test:

The first line contains 4
integers n,m,a,b (2≤n≤105,0≤m≤5?105,1≤a,b≤109). Each of the following m lines contains 2 integers ui,vi,
 which denotes(表示) cities ui and vi are connected by highway(公路). (1≤ui,vi≤n,ui≠vi

).
Output

For each test, write 1

integer(整数) which denotes(表示) the minimum(最小的) time.
Sample Input

3 2 1 3
1 2
2 3
3 2 2 3
1 2
2 3

Sample Output

2

3


题意:给一个无相完全图,给出的输入边的权值为 a,其它未知的权值都是 b
      求: 1  到  n 的最短 路径。
      
思路:最短路径只有两种可能。
      1> 以a为权值边 直接从 1到 n 和以 b为权值边 跑一遍最短路 两者取最小
      2> 以b为权值边 直接从 1到 n 和以 a为权值边 跑一遍最短路 两者取最小  
      
      由于数据量比较大,我们肯定要用邻接表 建图。 对于第二种情况我们用邻接表加 spfa 跑一遍 完全能求出来但第一种情况如何建图,如何求,一直思考不出来,看了这位大神用 集合实现 。用搜索的形式求出 补图,并同时求最短路。
感觉很巧妙,真是太厉害了。


大神 博客  http://blog.csdn.net/lvshubao1314/article/details/48848319


#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <set>//相同的数 不共存 #include <queue>#define inf 0x3f3f3f3fusing namespace std;long long dist[100010];int head[100010];bool vis[100010];set<int>st,ts; //定义 两个集合 set<int>::iterator it;      //迭代器 struct Node{int v;int w;int next;}edge[1000010];long long a,b;int n,m,num;void add_edge(int u,int v){edge[num].v = v;edge[num].w = a;edge[num].next = head[u];head[u] = num++; }long long spfa(){int u,v,i,w;queue<int> q;q.push(1);memset(dist,inf,sizeof(dist));memset(vis,false,sizeof(vis));dist[1] = 0;vis[1] = true;while(!q.empty()){u = q.front();q.pop();vis[u] = false;for(i=head[u];i!=-1;i=edge[i].next){v = edge[i].v;w = edge[i].w;if(dist[v]>dist[u]+w){dist[v] = dist[u] + w;if(!vis[v]){vis[v] = true;q.push(v);}}}}return dist[n]<b ? dist[n]:b;}long long bfs(){int i,u,v;    dist[n]=inf;    st.clear(); ts.clear();    for(i=2;i<=n;i++)     { st.insert(i);//把数放入集合中 }     queue<int>q;    q.push(1);    dist[1]=0;    while(!q.empty())    {        u=q.front();        q.pop();        for(i=head[u];i!=-1;i=edge[i].next)        {            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);            dist[*it]=dist[u]+1;        }        st.swap(ts); //把两集合内的元素互换         ts.clear();  //当前集合内的元素删去     }    return dist[n]*b<a ? dist[n]*b:a;}int main(){while(scanf("%d%d%lld%lld",&n,&m,&a,&b)!=EOF){int i,j,u,v;bool f = false;memset(head,-1,sizeof(head));for(i=0;i<m;i++){scanf("%d%d",&u,&v);if(u>v){swap(u,v);}add_edge(u,v);add_edge(v,u);if(u==1 && v==n){f = true;}}num = 0;if(f){printf("%lld\n",bfs());}else{printf("%lld\n",spfa());}}return 0;}


0 0
原创粉丝点击