zoukankan      html  css  js  c++  java
  • LightOJ1074(spfa+dfs标记负环及负环能够到达的点)

    题目链接:https://vjudge.net/problem/LightOJ-1074

    题意:简化题意后就是给了一个有向图(不一定连通),n个点,m条有向边(边权可为负),求点1到其它点的最短路(其中不能到达的点或者最短距离<3的输出'?',其余的输出相应的最短路即可)。

    思路:因为有负权边,那么不能用dijkstra,可以用spfa来做,显然不可达的(dis[i]==inf)输出'?'即可,最短距离<3(dis[i]<3)的输出'?',另外负环上的点以及从负环能够到达的点都直接输出'?',因为他们的最短距离是无穷小。然后用spfa求最短路,并标记负环上和从负环能到达的点,用dfs标记。

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    const int maxn=205;
    const int maxm=40005;
    const int inf=0x3f3f3f3f;
    int T,cas,n,m,q,cnt,loop,bn[maxn],head[maxn],vis[maxn],dis[maxn],upd[maxn];
    int f[maxn];
    
    struct node{
        int v,w,nex;
    }edge[maxm];
    
    void adde(int u,int v,int w){
        edge[++cnt].v=v;
        edge[cnt].w=w;
        edge[cnt].nex=head[u];
        head[u]=cnt;
    }
    
    void dfs(int u){
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            if(f[v]) continue;
            f[v]=1;
            dfs(v);
        }
    }
    
    void spfa(){
        queue<int> que;
        for(int i=1;i<=n;++i)
            vis[i]=0,dis[i]=inf,upd[i]=0,f[i]=0;
        que.push(1);
        vis[1]=1,dis[1]=0,upd[1]=1;
        while(!que.empty()){
            int u=que.front();que.pop();
            vis[u]=0;
            if(f[u]) continue;
            for(int i=head[u];i;i=edge[i].nex){
                int v=edge[i].v,w=edge[i].w;
                if(dis[v]>dis[u]+w){
                    dis[v]=dis[u]+w;
                    if(!vis[v]){
                        ++upd[v];
                        if(upd[v]>n){
                            f[u]=1;
                            dfs(u);
                        }
                        else{
                            vis[v]=1;
                            que.push(v);
                        }
                    }
                }
            }
        }
    }
    
    int main(){
        scanf("%d",&T);
        while(T--){
            printf("Case %d:
    ",++cas);
            scanf("%d",&n);
            cnt=0;
            for(int i=1;i<=n;++i)
                head[i]=0;
            for(int i=1;i<=n;++i)
                scanf("%d",&bn[i]);
            scanf("%d",&m);
            for(int i=1;i<=m;++i){
                int u,v;
                scanf("%d%d",&u,&v);
                adde(u,v,(bn[v]-bn[u])*(bn[v]-bn[u])*(bn[v]-bn[u]));
            }
            spfa();
            scanf("%d",&q);
            for(int i=1;i<=q;++i){
                int tmp;
                scanf("%d",&tmp);
                if(f[tmp]||dis[tmp]==inf||dis[tmp]<3)
                    printf("?
    ");
                else
                    printf("%d
    ",dis[tmp]);
            }
        }
        return 0;
    }
  • 相关阅读:
    MySQL常用命令
    Jstack、Jmap命令简单使用
    MySQL慢查询日志ES索引模板
    MySQL二进制安装部署
    varnish启动报错
    基础训练 Sine之舞
    基础训练 FJ的字符串
    基础训练 芯片测试
    基础训练 龟兔赛跑预测
    基础训练 回形取数
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/12251701.html
Copyright © 2011-2022 走看看