• SPFA求负环


    ( O(n*m)spfa求负环时间复杂度较高\ 负环:图中存在一个环,环上个边的权值和为负数\ 01分数规划\ 求负环的方法,基于SPFA:\ (1)统计某个点入队的次数,如果某个点入队n次,则说明存在负环\ (2)统计当前每个点的最短路所含的边数,如果某点的最短路的边数>=n,则存在负环。\ 图中的负环不一定从1点点走到,它可以从任何一个位置开始走,走到负环。\ 处理方法:\ 1.一开始让所有n个点入队,即假设有一个虚拟源点,源点到n个点的距离为0;\ 2.为什么dis[N]不用初始化为0x3f3f3f3f,dis[N]可以任意初始化\ 因为,如果存在一个负环<==>某些点到虚拟源点的距离是(—无穷),\ 因为w[i]是有限值,spfa每在负环上转一圈,dis都会减一个有限值,\ 但是,dis[负环]上的点会变成负无穷,所以spfa一定会在某个点满足判断负环条件的时候退出\ 3.floyd和bellman-ford中0x3f3f3f3f/2的问题,如果1号点和其他点不连通,2->3,3会被2更新成0x3f3f3f3f-x eq0x3f3f3f3f 当所有点入队次数超过2n时,我们认为图中很大可能存在负环。(取巧做法) )

    1165. 单词环

    /*
    每个字符串当成一个点,1e5个点,每个字符串相同
    对于每个点,该点后可以连任何一个点,n-1
    边数为n^2级别
    将0~26^2每个十进制数看成一个点,每个字符串看成一条边
    从aa-zz编号从0~675,一共676个点
    1e5条边.
    */
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    
    const int N=700,M=1e5+10;
    
    int h[N],e[M],ne[M],idx,w[M];
    int n,cnt[N];
    double dis[N];
    char str[M];
    bool st[N];
    void add(int a,int b,int c)
    {
        e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
    }
    // queue<int>que;
    int que[M*100],top;
    bool inline check(double mid)
    {
        memset(st,0,sizeof st);
        memset(cnt,0,sizeof cnt);
        //memset(que,0,sizeof que);重置top=0即可
        memset(dis,0,sizeof dis);
        top=0;
        for(int i=0;i<676;i++)
        {
            // que.push(i);
            que[++top]=i;
            st[i]=true;
        }
        int Count=0;
        while(top!=0)
        {
            // int t=que.front(),que.pop();
            int t=que[top--];
            st[t]=false;
    
            for(int i=h[t];~i;i=ne[i])
            {
                int j=e[i];
                if(dis[j]<dis[t]+w[i]-mid)
                {
                    dis[j]=dis[t]+w[i]-mid;
                    cnt[j]=cnt[t]+1;
                    if(++Count>=10000)return true;
                    if(cnt[j]>=N)
                        return true;
                    if(!st[j])
                    {
                        // que.push(j);
                        que[++top]=j;
                        st[j]=1;
                    }
                }
            }
        }
        return false;
    }
    
    int main()
    {
        while(scanf("%d",&n),n)
        {
            memset(h,-1,sizeof h);
            idx=0;
            for(int i=0;i<n;i++)
            {
                scanf("%s",str);
                int len=strlen(str);
                if(len>=2){
                    int left=(str[0]-'a')*26+str[1]-'a';
                    int right=(str[len-2]-'a')*26+str[len-1]-'a';
                    add(left,right,len);
                }
            }
            if(!check(0))//将M==0代入,没有正环
                cout<<"No solution"<<endl;
            else
            {
                double l=0,r=1000;
                while(r-l>1e-4)
                {
                    double mid=(l+r)/2;
                    if(check(mid))
                        l=mid;
                    else
                        r=mid;
                }
                // cout<<l<<endl;
                printf("%lf
    ",r);
            }
    
        }
        return 0;
    }
    坑点,memest()的时间复杂度是O(n)的,在多组测试数据中,使用for初始化比memset要快
    
  • 相关阅读:
    实验四实验报告————Android基础开发
    结对编程之四则运算——第二阶段报告
    实验三实验报告
    结对编程之四则运算——第一阶段报告
    第九周作业
    第八周作业
    第七周实验 实验2
    第七周作业
    第五周作业
    20155336 2017-2018 1 《信息安全系统设计基础》2017-9-27课堂实践
  • 原文地址:https://www.cnblogs.com/forward-985/p/14108577.html
Copyright © 2020-2023  润新知