zoukankan      html  css  js  c++  java
  • poj 3114 Countries in War

    强连通分量 + 最短路

    题意:城市间通信,给出n,n个城市,m,m条边,分别是端点和权,如果两个城市属于同一个国家,那么他们的通信时间为0,否则则按边权算一次的通信时间。两个城市被认为在一个国家,是从A能到B,从B也能到A。下面给出K个查询,能从u到v传递信息,需要多少时间,如果从u无法传递到v,输出那个长长的英文句子

    其实就是一个最短路,但是最短路的边权有讲究,虽然给出了u,v,w,但是u和v可能是同一个国家的,那么w应该是0而不是原来的值,所以要怎么判断u和v是不是在同一个国家,也就是他们可以互达,很明显不能查询一次判断一次,而是应该先搞出强连通分量,属于同一个强连通分量的两点间的边权为0

    这题不难,很直白,tarjan,和各种最短路的算法老实打就是了

    //强连通分量+最短路
    //属于一个强连通分量的点,路径为0,否则按原边权
    
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    #define N 510
    #define M 250010
    #define INF 0x3f3f3f3f
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    
    int n,tot;
    int head[N];
    struct edge
    {
        int u,v,w,next;
    }e[M];
    int dfn[N] , low[N] , belong[N] , dcnt , bcnt;
    int stack[N] , top;
    bool ins[N];
    int d[N][N];
    bool solve[N];
    
    void add(int u ,int v ,int w ,int k)
    {
        e[k].u = u; e[k].v = v; e[k].w = w;
        e[k].next = head[u]; head[u] = k;
    }
    
    void tarjan(int u)
    {
        stack[++top] = u;
        ins[u] = true;
        dfn[u] = low[u] = ++dcnt;
        for(int k=head[u]; k!=-1; k=e[k].next)
        {
            int v = e[k].v;
            if(!dfn[v])
            {
                tarjan(v);
                low[u] = min(low[u] , low[v]);
            }
            else if(ins[v])
                low[u] = min(low[u] , dfn[v]);
        }
        if(dfn[u] == low[u])
        {
            ++bcnt;
            while(1)
            {
                int x = stack[top--];
                ins[x] = false;
                belong[x] = bcnt;
                if(x == u) break;
            }
        }
    }
    
    void SCC()
    {
        dcnt = bcnt = top = 0;
        memset(dfn,0,sizeof(dfn));
        memset(ins,false,sizeof(ins));
        for(int i=1; i<=n; i++)
            if(!dfn[i])
                tarjan(i);
    }
    
    void SPFA(int s)
    {
        bool inq[N];
        queue<int>q;
        for(int i=0; i<=n; i++) 
        {
            d[s][i] = INF;
            inq[i] = false;
        }
        while(!q.empty()) q.pop();
        d[s][s] = 0;
        inq[s] = true;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            inq[u] = false;
            for(int k=head[u]; k!=-1; k=e[k].next)
            {
                int v = e[k].v;
                int w = e[k].w;
                if(belong[u] == belong[v]) w = 0;//同一个连通分量,权为0
                if(d[s][u] + w < d[s][v])
                {
                    d[s][v] = d[s][u] + w;
                    if(!inq[v])
                    {
                        inq[v] = true;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&tot)!=EOF && n)
        {
            memset(head,-1,sizeof(head));
            for(int i=0; i<tot; i++)
            {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                add(u,v,w,i);
            }
            SCC();
            int K;
            scanf("%d",&K);
            memset(solve,false,sizeof(solve));
            for(int k=0; k<K; k++)
            {
                int s,t;
                scanf("%d%d",&s,&t);
                if(!solve[s])
                {
                    solve[s] = true;
                    SPFA(s);
                }
                if(d[s][t] == INF) printf("Nao e possivel entregar a carta\n");
                else               printf("%d\n",d[s][t]);
            }
            printf("\n");
        }
        return 0;
    }
  • 相关阅读:
    WebGL——osg框架学习一
    webgl绘制粗线段
    ThreeJS实现波纹粒子效果
    WebGL——水波纹特效
    WebGL之shaderToy初使用
    有效提升职场竞争力
    Windows结构化异常处理浅析
    一起学习Boost标准库--Boost.StringAlgorithms库
    科学计算工具-Numpy初探
    进程动态拦截注入API HOOK
  • 原文地址:https://www.cnblogs.com/scau20110726/p/3070148.html
Copyright © 2011-2022 走看看