zoukankan      html  css  js  c++  java
  • uva 567 Risk

    UVA 其实挺折腾的,题目超长,然后题意可能很水,输入输出又奇葩,当做是磨练

    其实是最短路径的裸题。固定有20个点点,输入分为两部分,前部分有19行,每一行先输出一个n,表示这行有n个数字,然后输入n个数字。第i行输出的数字v表示i和v之间有边而且是无向边,所有边的权值都是1。

    输入的后部分是先输入一个m,表示有m个查询,下面m行输入点u,v输出两点间的最短路径

    显然就是Floy算法的裸题。但是新学了spafa,把spfa也放上来

    注意的是有20个点从1标号到20,但是输入只有19行,再者就是输出的格式也要注意,本题1Y,当做是练手啦

     SPFA

    //先给出spafa算法
    //这个代码中是得到了邻接矩阵后再输入m个查询
    //每得到一个查询进行一次spfa,时间比后面的floy慢了很多
    //并不是算法的效率问题,而是数据中有多个重复的查询
    //所以为了提高速度可以再得到邻接矩阵后先循环调用一次spfa
    //得到任意两个顶点的最短路,那么查询的时候直接输出即可
    //不过临时写的就没有这样做了,要实现不难,把d数组改为二维即可
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    #define N 25  //固定是20个点
    #define INF 1000000000
    int g[N][N];  //邻接矩阵
    int d[N];     //单源最短路径
    bool vis[N];  //标记那些点已经在队列中
    queue <int> q;
    int input()
    {
        int n,v;
        for(int i=1; i<=20; i++)
            for(int j=1; j<=20; j++)
                g[i][j]=INF;
        if(scanf("%d",&n)==EOF)  return 0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&v);
            g[1][v]=g[v][1]=1;
        }
        for(int i=2; i<=19; i++)
        {
            scanf("%d",&n);
            for(int j=1; j<=n; j++)
            {
                scanf("%d",&v);
                g[i][v]=g[v][i]=1;
            }
        }
    /*
        for(int i=1; i<=20; i++)
        {
            for(int j=1; j<=20; j++)
                if(g[i][j]==1) printf("1 ");
                else           printf("* ");
            printf("\n");
        }
    */
        return 1;
    }
    
    void spfa(int s)  //得到源点s
    {
        memset(vis,0,sizeof(vis));
        for(int i=1; i<=20; i++)  d[i]=INF;  //初始化
        d[s]=0;        //源点最短路为0
        while(!q.empty()) q.pop();
        q.push(s);  //源点入队
        vis[s]=1;   //标记已经在队中的元素
    
        while(!q.empty())
        {
            int u;
            u=q.front();  //读取队头元素
            q.pop();      //队头元素出队
            vis[u]=0;     //要记得清楚标记
            //对与点u相连的所有点v都进行松弛操作,如果有改变点v的估计值,那么点v入队
            for(int v=1; v<=20; v++)  //扫描邻接矩阵中的u行
                if( d[u]+g[u][v] < d[v] )  //可以更新d[v]
                {
                    d[v]=d[u]+g[u][v];
                    if(!vis[v])  //点v又不在队列中
                    {
                        q.push(v);  //点v入队
                        vis[v]=1;   //记得标记
                    }
                }
        }
    /*
        for(int i=1; i<=20; i++)
            printf("%d ",d[i]);
        printf("\n");
    */
        return ;
    }
    
    int main()
    {
        int T=0;
        while(1)
        {
            if(!input()) break;
            T++;
            int m;
            printf("Test Set #%d\n",T);
            scanf("%d",&m);  //读入m个查询
            for(int i=1; i<=m; i++)  //处理m个查询
            {
                int u,v;
                scanf("%d%d",&u,&v);
                spfa(u);
                printf("%2d to %2d: %d\n",u,v,d[v]);
            }
            printf("\n");
        }
        return 0;
    }

    Floy

    #include <stdio.h>
    #include <string.h>
    #define INF 1000000000
    #define N 25
    int d[N][N];
    
    void Floy()
    {
        int i,j,k;
        for(k=1; k<=20; k++)
            for(i=1; i<=20; i++)
                for(j=1; j<=20; j++)
                    if(d[i][j] > d[i][k]+d[k][j])
                        d[i][j]=d[i][k]+d[k][j];
        return ;
    }
    int main()
    {
        int T=0;
        int i,j,n,m,u,v;
        while(scanf("%d",&n)!=EOF)
        {
            T++;
            for(i=1; i<=20; i++)
                for(j=1; j<=20; j++)
                    if(i==j) d[i][j]=0;
                    else     d[i][j]=INF;
    
            for(i=1 ;i<=n; i++)
            {
                scanf("%d",&v);
                d[1][v]=d[v][1]=1;
            }
    
            for(u=2; u<=19; u++)
            {
                scanf("%d",&n);
                while(n--)
                {
                    scanf("%d",&v);
                    d[u][v]=d[v][u]=1;
                }
            }
    
            Floy();
            printf("Test Set #%d\n",T);
            scanf("%d",&m);  //m给个查询
            for(i=1; i<=m; i++)
            {
                scanf("%d%d",&u,&v);
                printf("%2d to %2d: %d\n",u,v,d[u][v]);
            }
    
            printf("\n");
        }
        return 0;
    }
  • 相关阅读:
    虽然非常简单但是效果不错
    Google地图开发总结
    笔记(一):ES6所改良的javascript“缺陷”
    ex6的选择器
    android中的style部分属性值介绍
    Android ImageSwitcher
    c# Winform退出程序的方法
    Android ImageView获取网络图片
    循环向数据库(sql server)插入10W条数据
    Android Handler+Thread实现更新Ui
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2756154.html
Copyright © 2011-2022 走看看