URAL 1072 Routing

本文介绍了一种基于广度优先搜索(BFS)的网络寻径算法实现,用于解决复杂网络环境中从源主机到目标主机的可达性及路径寻找问题。通过构建主机间的连接图并利用BFS算法,实现了高效查找最短路径的功能。

    链接:http://vjudge.net/problem/viewProblem.action?id=14085

    复杂的建图啊!但核心代码只是输出路径的 BFS。


#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>

using namespace std;

#define maxn 1003
#define INF 0x3f3f3f3f

int n,k,netNum,st,ed;
int graph[maxn][maxn],ever[maxn];
map<string,int>host; //记录每个网络所对应的一个整数
vector<int> nets[maxn]; //存每个网络里面所有主机
bool flag; //是否可以到达目的主机

//将数字转换为8位二进制
string toBin(int x)
{
    string ans = "";
    while(x)
    {
        int t = x%2;
        ans += '0' + t;
        x /= 2;
    }
    if(ans.size() < 8)
    {
        for(int i = ans.size();i < 8;++i)
            ans += '0';
    }
    reverse(ans.begin(),ans.end());
    return ans;
}

//将数字转为字符串
string toString(int x)
{
    string ans = "";
    while(x)
    {
        int t = x%10;
        ans += '0'+t;
        x /= 10;
    }
    reverse(ans.begin(),ans.end());
    return ans;
}

//找到子网掩码第一个 0
int find(string mask)
{
    for(int i = 0;i < mask.size();++i)
    {
        if(mask[i] == '0') return i;
    }
    return mask.size();
}

void init()
{
    memset(graph,0,sizeof(graph));
    memset(ever,0,sizeof(ever));
    memset(nets,0,sizeof(nets));
    host.clear();
    netNum = 0;
    flag = 0;
    for(int i = 0;i < n;++i)
    {
        cin>>k;
        for(int j = 0;j < k;++j)
        {
            int x[6];
            char ch;
            cin>>x[0]>>ch>>x[1]>>ch>>x[2]>>ch>>x[3];
            string ip,mask; // Ip 和子网掩码
            ip = toBin(x[0]) + toBin(x[1]) + toBin(x[2]) + toBin(x[3]);
            cin>>x[0]>>ch>>x[1]>>ch>>x[2]>>ch>>x[3];
            mask = toBin(x[0]) + toBin(x[1]) + toBin(x[2]) + toBin(x[3]);
            int t = find(mask);
            string net = ip.substr(0,t);
            //cout<<endl<<ip.size()<<' '<<ip<<' '<<t<<' '<<net<<endl;
            int select; //该 IP 的网络号对应的数字
            if(!host.count(net))
            {
                host.insert(make_pair(net,netNum)); //将每个网络号映射到一个整数
                select = netNum++;
            }
            else select = host[net];
            nets[select].push_back(i+1); //把主机放到对应网络里面
        }
    }

    //根据每个网络号的主机建图,相同网络内的每两台主机间路径权值为 1
    for(int i = 0;i < netNum;++i)
    {
        int len = nets[i].size();
        for(int j = 0;j < len;++j)
        {
            for(int l = j+1;l < len;++l)
            {
                graph[nets[i][j]][nets[i][l]] = graph[nets[i][l]][nets[i][j]] = 1;
            }
        }
    }

    cin>>st>>ed;
}

struct node
{
    int num;
    string path;//存到达当前主机打路径
};

string solve()
{
    queue<node> q;
    node cur,next;
    cur.num = st;
    cur.path = toString(st);
    ever[st] = 1;
    q.push(cur);
    while(!q.empty())
    {
        cur = q.front();
        q.pop();
        if(cur.num == ed)
        {
            flag = 1;
            return cur.path;
        }
        for(int i = 1;i <= n;++i)
        {
            if(graph[cur.num][i] && !ever[i])
            {
                next = cur;
                next.num = i;
                next.path += " ";
                next.path += toString(i);
                ever[i] = 1;
                q.push(next);
            }
        }
    }
    return "No";
}

int main()
{
    while(cin>>n)
    {
        init();
        string ans = solve();
        if(flag)
        {
            cout<<"Yes"<<endl;
            cout<<ans<<endl;
        }
        else cout<<ans<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值