路由
【问题描述】
有一个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");
}