【路由】解题报告

                                   路由 

【问题描述】 

    有一个TCP/IP网络: 
    ?  每台计算机都有一个或多个网络接口。 
    ?  每个接口根据它的IP地址和子网掩码来识别:即两个4字节的数,两个字 
        节之间有一个”.”号.子网掩码有一个二进制表示法:有k个”1”,然 
        后是 m 个”0”,k+m=8*4=32(如 212.220.35.77 是一个 IP 地 
        址,255.255.255.128是一个子网掩码)。 
    ?  两台计算机如果属于同样的子网,当且仅当(IP1 AND NETMASK1)=(IP2 
        ANDNETMASK2),其中IPi和NETMASKi是第i台计算机的IP地址和子网 
        掩码。 
    ?  在一个子网里,两台计算机可以直接传递消息包。 
    ?  如果两台计算机属于不同的子网,消息包的传递需要通过其他的计算机. 
        消息包能通过一个具有两个子网接口的计算机从一个子网传递到另一个 

    你的任务是找到两个给定计算机之间消息传递的最短路. 

【输入文件】 

    第一行是一个数N,表示网络中有N台计算机,然后是N个部分,描述每台计算 
机的接口,每一部分第一行是整数K表示该计算机的接口数,然后是K行,描述每 
个接口:它的IP地址和子网掩码,最后一行是两个整数,给你的所要求路线的两 
台计算机.其中2<=N<=90andK<=5 

【输出文件】 

    如果路线存在输出”Yes”,然后下一行是消息包在路线上传递时所依次经过 
的计算机号,如果路线不存在,则输出”No”。 

【输入样例】 

    6 
    2 
    10.0.0.1255.0.0.0 
    192.168.0.1255.255.255.0 
    1 
    10.0.0.2255.0.0.0 
    3 
    192.168.0.2255.255.255.0 
    212.220.31.1255.255.255.0 
    212.220.35.1255.255.255.0 
    1 
    212.220.31.2255.255.255.0 
    2 
    212.220.35.2255.255.255.0 
    195.38.54.65255.255.255.224 
    1 
    195.38.54.94255.255.255.224 
    16 

【输出样例】 

         Yes 
         1356 


这道题的模型比较复杂,但是程序其实很简单。

一道裸spfa。主要是建边的时候比较复杂

根据题设,每一个数字对应的权值为2^1、2^8、2^16、2^24

建边的条件是两台计算机至少有两个接口的IP&Netmask值相同。

0&0=0

1&0=0

1&1=1

#include <cstdio>

long g[92];
long n;long k;
unsigned long cmptr1[92][7];
unsigned long cmptr2[92][7];
const long oo = 0x7fff0000;
long dist[92];
long map[92][92];
long p;long q;
long que[10000000];
bool used[92];

void spfa()
{
	long l=0;long r=0;
	
	for (long i=1;i<n+1;i++)
	{
		dist[i] = 0x7fff0000;
	}
	dist[p] = 0;
	r++;
	que[r] = p;
	while (l<r)
	{
		l++;
		long now = que[l];
		used[now] = false;
		for (long i=1;i<n+1;i++)
		{
			if (i==now) continue;
			if (dist[now]+map[now][i]<dist[i])
			{
				g[i] = now;
				dist[i]=dist[now]+map[now][i];
				if (!used[i])
				{
					used[i] = true;
					r++;
					que[r] = i;
				}
			}
		} 
	}
}

void output(long l)
{
	if (g[l]==p)
	{
		printf("%ld ",p);
		return;
	}
	output(g[l]);
	printf("%ld ",g[l]);
}

int main()
{
	freopen("route.in","r",stdin);
	freopen("route.out","w",stdout);
	scanf("%ld",&n);
	for (long i=1;i<n+1;i++)
	{
		scanf("%ld",&k);
		for (long j=1;j<k+1;j++)
		{
			unsigned long a1;unsigned long a2;unsigned long a3;unsigned long a4;
			unsigned long b1;unsigned long b2;unsigned long b3;unsigned long b4;
			scanf("%lu.%lu.%lu.%lu ",&a1,&a2,&a3,&a4);
			scanf("%lu.%lu.%lu.%lu ",&b1,&b2,&b3,&b4);
			cmptr1[i][++cmptr1[i][0]] = (a1<<24)+(a2<<16)+(a3<<8)+a4;
			cmptr2[i][++cmptr2[i][0]] =	(b1<<24)+(b2<<16)+(b3<<8)+b4;
		}
	}
	scanf("%ld%ld",&p,&q);

	for (long a=1;a<n+1;a++)
	{
		for (long b=1;b<n+1;b++)
		{
			if (a==b) continue;
			for (long i=1;i<cmptr1[a][0]+1;i++)
			{
				for (long j=1;j<cmptr1[b][0]+1;j++)
				{
					if ((cmptr1[a][i]&cmptr2[a][i])==(cmptr1[b][j]&cmptr2[b][j]))
					{
						map[a][b]=1;
						i=cmptr1[a][0]+1;
						break;
					}
				}
			}
			if (map[a][b]!=1)
				map[a][b]=oo;
		}
	}
	spfa();
	if (dist[q]<oo)
	{
		printf("Yes\n");
		output(q);
		printf("%ld ",q);
	}
	else
		printf("No");
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值