• 【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. }  
  • 相关阅读:
    yum源
    存储计量单位排序
    博客园代码高亮
    磁盘配置
    软件包安装
    网络配置
    用户、组及权限控制
    Android开发项目中常用到的开源库
    使用百度地图时,Application类的onCreate执行两次的解决方案
    计算从1到n中,出现某位数字的次数
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9876084.html
Copyright © 2020-2023  润新知