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;
}
posted @ 2012-11-05 23:21  Titanium  阅读(417)  评论(0编辑  收藏  举报