【NOIP模拟】最短路

题面

小 C 终于被小 X 感动了,于是决定与他看电影,然而小 X 距离电影院非常远,现在假设每条道路需要花费小 X 的时间为 1,由于有数以万计的好朋友沿路祝贺,导致小 X在通过某些路不得不耗费 1 的时间来和他们聊天,尽管他希望尽早见到小 C,所以他希望找到一条最快时间到达电影院的路。

一开始小 X 在 1 号点,共有 N 个点,M 条路,电影院为 T 号点

对于 30%的数据:n<=10,m<=20;
对于 60%的数据:n<=1 000,m<=20 000;
对于 100%的数据:n<=5 000 000,m<=10 000 000,1<=w<=2。

分析

因为数据是随机生成的,太弱了,于是放过了spfa(卡住了没有优化的dijkstra 23333)

但是正解其实是拆边

由于观察到边权只会是1或2,可以将其拆2的边为1和1,然后直接用bfs即可,复杂度为O(n+m)

代码

spfa+floyd(怕被卡 留点分保命)

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define N 110  
  4. #define RT register  
  5. #define MAXN 5000050  
  6. int n,m,t,cnt;  
  7. int g[N][N],d[MAXN],vis[MAXN],first[MAXN];  
  8. queue<int>q;  
  9. struct email  
  10. {  
  11.     int u,v,w;  
  12.     int nxt;  
  13. }e[MAXN*4];  
  14. template<class T>  
  15. inline void read(T &x)  
  16. {  
  17.     x=0;int f=1;static char ch=getchar();  
  18.     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  
  19.     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  
  20.     x*=f;  
  21. }  
  22. inline void add(int u,int v,int w)  
  23. {  
  24.     e[++cnt].nxt=first[u];first[u]=cnt;  
  25.     e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;  
  26. }  
  27.   
  28. void spfa(int x)  
  29. {  
  30.     memset(d,0x3f,sizeof(d));  
  31.     q.push(x);vis[x]=1;d[x]=0;  
  32.     while(!q.empty())  
  33.     {  
  34.         int u=q.front();q.pop();vis[u]=0;  
  35.         for(RT int i=first[u];i;i=e[i].nxt)  
  36.         {  
  37.             int v=e[i].v,w=e[i].w;  
  38.             if(d[v]>d[u]+w)  
  39.             {  
  40.                 d[v]=d[u]+w;  
  41.                 if(!vis[v])  
  42.                 {  
  43.                     q.push(v);  
  44.                     vis[v]=1;  
  45.                 }  
  46.             }  
  47.         }  
  48.     }  
  49. }  
  50.   
  51. int main()  
  52. {  
  53.     freopen("short.in","r",stdin);  
  54.     freopen("short.out","w",stdout);  
  55.     memset(g,0x3f,sizeof(g));  
  56.     read(n);read(m);read(t);  
  57.     if(n<=100)  
  58.     {  
  59.         for(RT int i=1;i<=m;i++)  
  60.         {  
  61.             int u,v,w;  
  62.             read(u),read(v),read(w);  
  63.             g[u][v]=g[v][u]=min(g[u][v],w);  
  64.         }  
  65.         for(RT int k=1;k<=n;k++)  
  66.             for(RT int i=1;i<=n;i++)  
  67.                 for(RT int j=1;j<=n;j++)  
  68.                     g[i][j]=min(g[i][j],g[i][k]+g[k][j]);  
  69.         printf("%d ",g[1][t]);  
  70.         return 0;  
  71.     }  
  72.     for(RT int i=1;i<=m;i++)  
  73.     {  
  74.         int u,v,w,ok=0;  
  75.         read(u),read(v),read(w);  
  76.         add(u,v,w);add(v,u,w);  
  77.     }  
  78.     spfa(1);  
  79.     printf("%d ",d[t]);  
  80.     return 0;  
  81. }  

拆边(std)

  1. #include<cstdio>  
  2.   
  3. int n, m, cnt, q, num;  
  4. int head[20000010], d[20000010], v[20000010];  
  5. struct edge{int to, next;} e[40000010];  
  6.   
  7. void ins(int x, int y)  
  8. {  
  9.     e[++cnt].to = y; e[cnt].next = head[x]; head[x] = cnt;  
  10.     e[++cnt].to = x; e[cnt].next = head[y]; head[y] = cnt;  
  11. }  
  12.   
  13. char B[150 * 1024 * 1024], *S = B;  
  14. #define getchar() (*S++)  
  15. int read()  
  16. {  
  17.     int x = 0char c = getchar();  
  18.     while (c < '0' || c > '9') c = getchar();  
  19.     while (c >= '0' && c <= '9') {x = (x << 3) + (x << 1) + c - '0'; c = getchar();}  
  20.     return x;  
  21. }  
  22.   
  23. int main()  
  24. {  
  25.     freopen("short.in""r", stdin);  
  26.     freopen("short.out""w", stdout);  
  27.     int x, y, z, p, h, t, i;  
  28.     fread(B, 1150 * 1024 * 1024, stdin);  
  29.     n = read(); m = read(); q = read();  
  30.     num = n;  
  31.     for(i = 1; i <= m; ++i)  
  32.     {  
  33.         x = read(); y = read(); z = read();  
  34.         if(z == 1) ins(x, y);  
  35.         else ins(x, ++num), ins(num, y);  
  36.     }  
  37.     h = t = 1; d[h] = 1; v[1] = 1;  
  38.     while(h <= t)  
  39.     {  
  40.         x = d[h++];  
  41.         for(i = head[x]; i; i = e[i].next)  
  42.             if (!v[e[i].to]) {v[e[i].to] = v[x] + 1; d[++t] = e[i].to;}  
  43.     }  
  44.     printf("%d ", v[q] - 1);  
  45.       
  46.     return 0;  
  47. }  
原文地址:https://www.cnblogs.com/NSD-email0820/p/9876084.html