zoukankan      html  css  js  c++  java
  • 一个输入引起的超时

    引言

    最的在做一本通网站上的题目,各种超时让人有些烦恼。今天一大早就做一本通网站1378题(http://ybt.ssoier.cn:8088/problem_show.php?pid=1378),一看数据规模不大(n=80),便随手写起来。先来一个SPFA吧,这几天觉得这算法还不错,代码也很快出来了。

    //1378:最短路径(shopth)
    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=81;
    const int inf=1e9;
    int link[N][N],msg[N][N],dis[N],p[N],n,s;
    int que[N*2],h=0,t=1,cx,tx;
    int read()
    {
        int x=0,f=1,cnt=0;
        char ch='';
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        do
        {
            if(ch=='-')f=-1;
            else cnt++,x=x*10+ch-'0';
            ch=getchar();
        }while(ch>='0'&&ch<='9');
        if(x==0&&cnt==0)x=inf;
        else x*=f;
        return x;
    }
    int main()
    {
        ios::sync_with_stdio(0);
        cin>>n>>s;
        
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                cx=read();
                link[i][j]=cx;
                if(cx<inf&&i!=j)msg[i][++msg[i][0]]=j;
            }
        //因为有负权边,不可用dijkstra,故采用SPFA 
            for(int j=1;j<=n;j++)dis[j]=inf,p[j]=0;
            dis[s]=0,h=0,t=1,que[1]=s;
            while(h!=t)
            {
                h=h%161+1;//用循环队列 
                cx=que[h],p[cx]=0;
                for(int j=1;j<=msg[cx][0];j++)
                {
                    tx=msg[cx][j];
                    if(dis[tx]>dis[cx]+link[cx][tx])
                    {
                        dis[tx]=dis[cx]+link[cx][tx];
                        if(p[tx]==0)
                            t=t%161+1,que[t]=tx,p[tx]=1;
                    }
                }
            cout<<'('<<s<<"->"<<i<<")="<<dis[i]<<endl; 
        }
        return 0;
    }
    第一版代码

    可提交后让我大跌眼镜,10个点超时。回头再看,感觉没问题啊,read()读入函数几乎是网传的快读程序了,应该没啥问题啊,难道SPFA出错了?虽然自我感觉没啥错,但既然报错还是改改吧,我看了下数据规模不大,干脆来个弗洛伊德得了,这个简单不易错的。可结局依然是10点超时。难道是输入错了?好吧,换一个。

    //1378:最短路径(shopth)
    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=81;
    const int inf=1e9;
    int link[N][N],msg[N][N],dis[N],p[N],n,s;
    //msg[x][y]存储以x为起点的边信息,msg[x][0]存储边的条数,其后依次存储各边终点 
    int que[N*2+3],h=0,t=1,cx,tx;
    //int read()
    //{
    //    int x=0,f=1,cnt=0;
    //    //cnt记录输入的数字个数,若为0则说明只输入了一个-(无边) 
    //    char ch='';
    //    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    //    do
    //    {
    //        if(ch=='-')f=-1;
    //        else cnt++,x=x*10+ch-'0';
    //        ch=getchar();
    //    }while(ch>='0'&&ch<='9');
    //    if(cnt==0)x=inf;
    //    else x*=f;
    //    return x;
    //}
    int get(string s0)
    {
        if(s0=="-")return inf;
        int f=1,x=0;
        for(int i=0;i<s0.length() ;i++)
        {
            if(s0[i]=='-')f=-1;
            else x=x*10+s0[i]-'0';
        }
        return x*f;
    }
    int main()
    {
        ios::sync_with_stdio(0);
        cin>>n>>s;
        string ss;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                //cx=read();
                cin>>ss;            
                link[i][j]=get(ss);
                if(i!=j&&cx<inf)msg[i][++msg[i][0]]=j;
            }
        //因为有负权边,不可用dijkstra,故采用SPFA 
        for(int j=1;j<=n;j++)dis[j]=inf,p[j]=0;
        dis[s]=0,h=0,t=1,que[1]=s;
        while(h!=t)//队列中最多n个元素,不可能队满,h=t则说明队空 
        {
            h=h%(N*2)+1;//用循环队列 
            cx=que[h],p[cx]=0;
            for(int j=1;j<=msg[cx][0];j++)
            {
                tx=msg[cx][j];
                if(dis[tx]>dis[cx]+link[cx][tx])//tx的值因cx而更新 
                {
                    dis[tx]=dis[cx]+link[cx][tx];//更新tx的值 
                    if(p[tx]==0)//如果tx没在队列中则让tx入队 
                        t=t%(N*2)+1,que[t]=tx,p[tx]=1;
                }
            }
        }
    //    for(int k=1;k<=n;k++)
    //        for(int i=1;i<=n;i++)
    //            for(int j=1;j<=n;j++)
    //                if(link[i][j]>link[i][k]+link[k][j])
    //                     link[i][j]=link[i][k]+link[k][j];
        for(int i=1;i<=n;i++) 
            if(i!=s)cout<<'('<<s<<" -> "<<i<<") = "<<dis[i]<<endl; 
        return 0;
    }

    提交,没问题。看来真是输入出了问题。终于在之江学院石老师的指点下明白了问题所在。

    前几天做1346最后一个点超时,几经周折发现取消同步后的cin能过,所以在喜欢上了取消同步的cin输入,但这一次就出在这里,取消同步后cin和getchar()就不能混用了,当然解决方案很简单,要么去掉“取消同步”,要么改掉cin,用scanf代替,问题解决。

    目前个人感觉在输入方面取消同步后的cin比scanf效率高,不取消同步的cin比scanf效率低,但取消同步似乎对输出无效。典型例子就是1205汉诺塔,用cout超时,用printf能过。取消同步无用。

  • 相关阅读:
    js中undefined,null,NaN的区别
    js中数字计算精度
    BestCoder Round #32
    POJ 2299 求逆序对(归并排序或树状数组)
    POJ 2603
    CodeForces 515C
    POJ 1853 背包问题
    UVA 10115 子符串替换
    POJ 1155 树状dp
    HDU 2196 树状dp 求树中节点之间的最长距离
  • 原文地址:https://www.cnblogs.com/wendcn/p/12356433.html
Copyright © 2011-2022 走看看