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

    http://poj.org/problem?id=3114

     题目大意:

    n个间谍 他们之间传送信息需要一定的时间

    一个联通分量里面的间谍属于一个国家,之间的信息传递不需要时间

    然后问你从一个间谍传一个信息到另一个间谍那需要最少时间 也可能传不到

    联通缩点+最短路

    缩点所得到的新图 可能是因为有重边或是太稠密 用邻接表容易超时

    基本步骤:

    1,输入去重边

    2,Tarjan缩点

    3,重新调整缩点后间谍之间的信息传递时间

    4,最短路

    注意: 图有可能不完全连通

    代码及其注释:

    #include<iostream>
    #include<cstring>
    #include<stack>
    #include<cstdio>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    
    using namespace std;
    
    const int M=1000000002;
    const int N=515;
    struct node
    {
        struct tt *next;
    }mem[N];
    struct node1
    {
        struct tt *next;
    }remem[N];
    struct tt
    {
        struct tt *next;
        int j;
    };
    bool in[N];
    bool visited[N];
    int deep;
    stack<int>str;
    int dfn[N];
    int low[N];
    int uppoint[N];
    int time[N][N];
    inline void build(int i,int j)
    {
        struct tt *t=new tt;
        t->j=j;
        t->next=mem[i].next;
        mem[i].next=t;
    }
    inline void Clearlist(int n)
    {
        for(int i=1;i<=n;++i)
        {
            mem[i].next=NULL;
        }
    }
    void Tarjan(int x)//缩点
    {
        ++deep;
        dfn[x]=low[x]=deep;
        visited[x]=true;
        in[x]=true;
        str.push(x);
        struct tt *t=mem[x].next;
        while(t!=NULL)
        {
            if(visited[t->j]==false)
            {
                Tarjan(t->j);
                low[x]=min(low[x],low[t->j]);
            }else if(in[t->j]==true)
            {
                low[x]=min(low[x],dfn[t->j]);
            }
            t=t->next;
        }
        if(low[x]==dfn[x])
        {
            while(str.top()!=x)
            {
                uppoint[str.top()]=x;
                in[str.top()]=false;
                str.pop();
            }
            uppoint[str.top()]=x;
            in[str.top()]=false;
            str.pop();
        }
    }
    void dfs(int x)//调整缩点后有用点之间的信息传递时间
    {
        visited[x]=true;
        struct tt *t=mem[x].next;
        while(t!=NULL)
        {
            if(uppoint[x]!=uppoint[t->j])
            {
                time[uppoint[x]][uppoint[t->j]]=min(time[uppoint[x]][uppoint[t->j]],time[x][t->j]);
            }
            if(!visited[t->j])
            {
                dfs(t->j);
            }
            t=t->next;
        }
    }
    int mintime(int st,int nd,int n)//求最短路
    {
        if(st==nd)
        return 0;
        int dist[N];
        memset(visited,false,sizeof(visited));
        for(int i=1;i<=n;++i)
        if(time[st][i]==-1)
        dist[i]=M;
        else
        dist[i]=time[st][i];
        visited[st]=true;
        for(int w=1;w<n;++w)
        {
            int MIN=M;int k=-1;
            for(int i=1;i<=n;++i)
            {
                if(!visited[i]&&dist[i]<MIN)
                {
                    MIN=dist[i];k=i;
                }
            }
            if(k==-1)
            break;
            if(k==nd)
            break;
            visited[k]=true;
            for(int i=1;i<=n;++i)
            {
                if(dist[i]>dist[k]+time[k][i])
                dist[i]=dist[k]+time[k][i];
            }
        }
        return dist[nd];
    }
    int main()
    {
        int n,m,q;
        while(scanf("%d %d",&n,&m)!=EOF)
        {
            if(n==0&&m==0)
            break;
            for(int i=1;i<=n;++i)//初始化
            {
                for(int j=i;j<=n;++j)
                time[i][j]=time[j][i]=M;
            }
            while(m--)
            {
                int i,j,k;
                scanf("%d %d %d",&i,&j,&k);
                if(time[i][j]>k)//去重边
                time[i][j]=k;
            }
            for(int i=1;i<=n;++i)
            {
                for(int j=1;j<=n;++j)
                {
                    if(time[i][j]!=M)//建原图
                    build(i,j);
                }
            }
            memset(dfn,-1,sizeof(dfn));
            memset(visited,false,sizeof(visited));
            memset(in,false,sizeof(in));
            memset(uppoint,-1,sizeof(uppoint));
            while(!str.empty())
            str.pop();
            deep=0;
            for(int i=1;i<=n;++i)
            {
                if(dfn[i]==-1)//因为图有可能不完全联通
                Tarjan(i);
            }
            memset(visited,false,sizeof(visited));
            for(int i=1;i<=n;++i)
            {
                if(!visited[i])//因为图有可能不完全联通
                {
                    dfs(i);
                }
            }
            for(int i=1;i<=n;++i)
            {
                for(int j=1;j<=n;++j)
                {
                    if(i!=uppoint[i]||j!=uppoint[j])//处理一下非联通缩点之间的信息传递时间
                    time[i][j]=M;
                }
            }
            scanf("%d",&q);
            while(q--)
            {
                int i,j,k;
                scanf("%d %d",&i,&j);
                i=uppoint[i];j=uppoint[j];
                k=mintime(i,j,n);
                if(k==M)
                printf("Nao e possivel entregar a carta\n");
                else
                printf("%d\n",k);
            }
            printf("\n");
            Clearlist(n);
    
        }
        return 0;
    }
    
  • 相关阅读:
    什么是TCP, UDP, HTTP, HTTPS协议?
    Django 自定义分页器
    PHP7.3安装event扩展
    深入浅出 PHP SPL(PHP 标准库)(转)
    Centos7安装redis5.0.7
    useradd命令详解(转)
    centos7.5下安装rabbitmq服务端以及php扩展
    php-fpm启动,重启,退出
    深度好文:PHP写时拷贝与垃圾回收机制(转)
    非对称加密openssl协议在php7实践
  • 原文地址:https://www.cnblogs.com/liulangye/p/2532841.html
Copyright © 2011-2022 走看看