HLG 1348 最短路径[floyd]

Description
给出一个有向带权图G,针对该图有如下的两种操作:
(1)标记该图的一个点
(2)找到两点间的只通过已标记点的最短路径长度


输入:
输入包括多组测试,每组测试中第一行包括三个整数N,M,Q,N表示图中的节点数量,N<=300,
M表示边的数量,M<=100000;Q表示执行多少次操作,Q<=100000,所有点被编号为0,1,2,...,N-1,
最初所有的点都是未标记的,接下来M行每行包括三个整数x,y,c,表示从x到y有一条边长度为c,c>0,然
后为Q行,每行表示一次操作,0 x表示将点x标记,1 x y表示查找x到y的只通过已标记点的最短路径长度,
N=M=Q=0是输入结束。


输出:


输出以一行"Case #:"开始,#表示为第几组测试,从1开始
对于0 x操作,如果x已经被标记过了,输出"ERROR! At point x".
对于1 x y操作,如果x或y没有被标记过,输出"ERROR! At path x to y",如果无法从x通过标记过的节
点到达y,输出"No such path",否则输出要求的最短路径长度,每两组测试之间有一个空行。
Input
输入包括多组测试,每组测试中第一行包括三个整数N,M,Q,N表示图中的节点数量,N<=300,
M表示边的数量,M<=100000;Q表示执行多少次操作,Q<=100000,所有点被编号为0,1,2,...,N-1,
最初所有的点都是未标记的,接下来M行每行包括三个整数x,y,c,表示从x到y有一条边长度为c,c>0,然
后为Q行,每行表示一次操作,0 x表示将点x标记,1 x y表示查找x到y的只通过已标记点的最短路径长度,
N=M=Q=0是输入结束。
 
Output
输出以一行"Case #:"开始,#表示为第几组测试,从1开始
对于0 x操作,如果x已经被标记过了,输出"ERROR! At point x".
对于1 x y操作,如果x或y没有被标记过,输出"ERROR! At path x to y",如果无法从x通过标记过的节
点到达y,输出"No such path",否则输出要求的最短路径长度,每两组测试之间有一个空行。
 
Sample Input
5 10 10
1 2 6335
0 4 5725
3 3 6963
4 0 8146
1 2 9962
1 0 1943
2 1 2392
4 2 154
2 2 7422
1 3 9896
0 1
0 3
0 2
0 4
0 4
0 1
1 3 3
1 1 1
0 3
0 4
0 0 0
Sample Output
Case 1:
ERROR! At point 4
ERROR! At point 1
0
0
ERROR! At point 3
ERROR! At point 4

分析: 把floyd算法 分成n次松弛操作。

View Code
#include<stdio.h>
#include<string.h>
int g[303][303];
int v[303];
int main()
{
    int n,m,Q,a,b,c,i,j,ca=1,k,to=0;
    while(scanf("%d%d%d",&n,&m,&Q)!=EOF)
    {
        if(n==0&&m==0&&Q==0)
            break;
        memset(v,0,sizeof(v));
        memset(g,-1,sizeof(g));
        for(i=0;i<=n;i++)
            g[i][i]=0;
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
                if(a!=b&&(g[a][b]==-1||c<g[a][b]))
                    g[a][b]=c;
        }
        printf("Case %d:\n",ca++);
        while(Q--)
        {
            scanf("%d",&c);
            if(c==0)
            {
                scanf("%d",&k);
                if(v[k])
                printf("ERROR! At point %d\n",k);
                else
                {
                        v[k]=1;
                        for(i=0;i<n;i++)
                        {
                            if(g[i][k]>=0) 
                            for(j=0;j<n;j++)
                                  if(g[k][j]>=0&&(g[i][k]+g[k][j]<g[i][j]||g[i][j]<0))
                                    g[i][j]=g[i][k]+g[k][j];
                        }
                    
                }
            }
            else if(c==1)
            {
                scanf("%d%d",&a,&b);
                if(!v[a]||!v[b])
                  printf("ERROR! At path %d to %d\n",a,b);
                else if(g[a][b]==-1)
                  printf("No such path\n");
                else printf("%d\n",g[a][b]);
            }
        }
        printf("\n");
    }
    return 0;
}

 

posted @ 2012-04-20 00:11  'wind  阅读(231)  评论(0编辑  收藏  举报