zoukankan      html  css  js  c++  java
  • 洛谷 P1629 邮递员送信

    这个里面判断的东西比较多

    实际上不需要这么多的,数据给的很水

    完全可以加上重边自环什么的

    而且这道题完全暴力做n次dij(3*10^7比较危险)

    比较优化的方法是:

    第一遍dij算出邮递员到每个地方的距离

    第二遍反向建边,横容易看出邮递员到每个地方的距离都是每个地方到邮递员的距离

    这种方法就可以把单终点最短路径转变成单源最短路径

    另外说明一下,因为跑两遍Dij,为了便于区分分开写的,变量名最后是1的是第一次dij有关,为2 则是第二次dij

    上代码

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    
    using namespace std;
    
    int n,m;
    int h1[1926],h2[1926];   
    int s1,s2;
    struct edge{
        int next,to,dis;
    };
    int v1[1926],v2[1926];
    int d1[1926],d2[1926];
    edge e1[200860],e2[200860];
    int looker1[1020][1020];   //looker是得到i,j边距离最小值 
    int looker2[1020][1020];
    int l1[1020][1020];   //l1是标记i,j是否走过 
    int l2[1020][1020];
    
    void addedge1(int next,int to,int dis)
    {
        e1[++s1].dis=dis;
        e1[s1].next=h1[next];
        e1[s1].to=to;
        h1[next]=s1;
    }
    
    void addedge2(int next,int to,int dis)
    {
        e2[++s2].dis=dis;
        e2[s2].to=to;
        e2[s2].next=h2[next];
        h2[next]=s2;
    }
    
    void dij1(int start)
    {
        priority_queue <pair<int,int> > q;   //pair的用法 
        memset(d1,0x3f,sizeof(d1));
        memset(v1,0,sizeof(v1));
        q.push(make_pair(0,start));
        d1[1]=0;
        while(!q.empty())
        {
            int i,j,k;
            int t=q.top().second;
            q.pop();
            if(v1[t]) continue;
            v1[t]=1;  
            for(i=h1[t];i;i=e1[i].next)
            {
                j=e1[i].to;
                if(l1[t][j]) continue;  //l1是判断t和j边是否走过一次,如果走过了还能走由Dij性质得到有重边 
                l1[t][j]=1;
                k=looker1[t][j];
                if(d1[t]+k<d1[j])
                {
                    d1[j]=d1[t]+k;
                    q.push(make_pair(-d1[j],j));
                     //pair第一个数据是由小到大的,因此需要取相反数
                    //例如 5大于3,因此5先出队,但是取相反数之后-3就大与5了 
                }
            }
        }
    }
    
    void dij2(int start)
    {    
        priority_queue <pair<int,int> > q; 
        memset(d2,0x3f,sizeof(d2));  //因为求最小值所以初值赋为极大值 
        memset(v2,0,sizeof(v2));
        q.push(make_pair(0,start));
        d2[1]=0;
        while(!q.empty())
        {
            int i,j,k;
            int t=q.top().second;
            q.pop();
            if(v2[t]) continue;
            
            v2[t]=1;
            for(i=h2[t];i;i=e2[i].next)
            {
                j=e2[i].to;
                k=looker2[t][j];
                if(l2[t][j]) continue;
                l2[t][j]=1;
                if(d2[t]+k<d2[j])
                {
                    d2[j]=d2[t]+k;
                    q.push(make_pair(-d2[j],j));
                }
            }
        }
    }
    
    int main()
    {
        int i,j;
        scanf("%d %d",&n,&m);
        memset(looker1,0x3f,sizeof(looker1));
        memset(looker2,0x3f,sizeof(looker2));
        for(i=1;i<=m;i++)
        {
            int t1,t2,t3;
            scanf("%d %d %d",&t1,&t2,&t3);
            looker1[t1][t2]=min(looker1[t1][t2],t3);  //得到 t1,t2的最小值 
            looker2[t2][t1]=min(looker2[t2][t1],t3);
            addedge1(t1,t2,t3);
            addedge2(t2,t1,t3);  //反向建图 
        }
        int tot=0;
        dij1(1);
        dij2(1);
        for(i=1;i<=n;i++)
        {
            tot+=d1[i]+d2[i];
        }
        printf("%d",tot);
        return 0;
    }
  • 相关阅读:
    [转]ThinkPHP中如何使用原生SQL
    php定时回调接口
    [转]mysql dual虚拟表
    [转]mysql变量使用总结
    [转]使用mysql profiles 来查看sql 语句执行计划
    [转]Mysql中的SQL优化与执行计划
    [转]MySQL单列索引和组合索引的区别介绍
    前端开发框架
    sugar crm
    [转]MCC(移动国家码)和 MNC(移动网络码)
  • 原文地址:https://www.cnblogs.com/zsx6/p/11059345.html
Copyright © 2011-2022 走看看