140 - Bandwidth

来源:互联网 发布:抗战中日伤亡真实数据 编辑:程序博客网 时间:2024/04/29 01:54

Given a graph(V,E) where V is a set of nodes and E is a set of arcs in VxV, and an orderingon the elements in V, then the bandwidth of a node v isdefined as the maximum distance in the ordering between v andany node to which it is connected in the graph. The bandwidth of the orderingis then defined as the maximum of the individual bandwidths. For example,consider the following graph:

This can beordered in many ways, two of which are illustrated below:

For theseorderings, the bandwidths of the nodes (in order) are 6, 6, 1, 4, 1, 1, 6, 6giving an ordering bandwidth of 6, and 5, 3, 1, 4, 3, 5, 1, 4 giving anordering bandwidth of 5.

Write a programthat will find the ordering of a graph that minimizes the bandwidth.

Input

Input will consistof a series of graphs. Each graph will appear on a line by itself. The entirefile will be terminated by a line consisting of a single #. For eachgraph, the input will consist of a series of records separated by `;'. Eachrecord will consist of a node name (a single upper case character in the therange `A' to `Z'), followed by a `:' and at least one of its neighbors. Thegraph will contain no more than 8 nodes.

Output

Output willconsist of one line for each graph, listing the ordering of the nodes followed byan arrow (->) and the bandwidth for that ordering. All items must beseparated from their neighbors by exactly one space. If more than one orderingproduces the same bandwidth, then choose the smallest in lexicographicordering, that is the one that would appear first in an alphabetic listing.

Sample input

A:FB;B:GC;D:GC;F:AGH;E:HD

#

Sample output

A B C F G D H E-> 3

算法:

剪枝:不考虑效率,可以递归枚举全排列。考虑效率:首先记录下目前已经找到的最小宽带K,在后续的排列中,如果发现已经有某两个节点的距离大于或等于K,那么再怎么扩展也不可能比当前解更优,应该强制把它们“剪”掉,为解答树剪枝。除此之外,还可以剪掉更多的枝叶:如果在搜索到结点U时,U结点还有M个相邻点没有确定的位置,那么对于U结点来说,最理想的情况就是这M个结点紧跟在U后面,带宽至少为M,若M>=K,即“在最理想的情况下都不能得到比当前最优解更好的方案”,则应当剪枝。

代码:

#include<iostream>

#include<cstring>

#include<cctype>

#include<algorithm>

#include<cmath>

using namespacestd;

 

char node[10];//存储节点名

int G[30][30];//存储图,若相连,则值为1,不相连,值为0

 

bool check(charu);//检查节点名是否在数组中已经存在

 

int main()

{

    string s;

   while(getline(cin,s)&&s!="#")

    {

        memset(node,0,sizeof(node));

        memset(G,0,sizeof(G));

        int cur=0;

        for(int i=0; i<s.size(); i++)

        {

           if(isalpha(s[i])&&s[i+1]==':')

            {

                char u=s[i];

                if(check(u))

                {

                    node[cur++]=u;

                }

                for(i=i+2; i<s.size()&&s[i]!=';';i++)//不要越界访问

                {

                    G[u-'A'][s[i]-'A']=1;

                    G[s[i]-'A'][u-'A']=1;

                    if(check(s[i]))

                    {

                        node[cur++]=s[i];

                    }

                }

            }

        }

        int big=strlen(node);

        sort(node,node+big);

        int wide=0;//总最优解

        int wide0=0;//对应第一组的最优解

        for(int i=0; i<big; i++)

        {

            int wide1=0;//对应第一组中每一个节点的最优解

            for(int j=0; j<big; j++)

            {

                if(G[node[i]-'A'][node[j]-'A'])//若两点相连

                {

                    int m=-1,n=-1;

                    while(node[++m]!=node[i]);

                    while(node[++n]!=node[j]);

                    wide1=max(wide1,abs(m-n));//找到单一节点的最大带宽

                }

            }

            wide0=max(wide0,wide1);//找到第一组的最大带宽

        }

        wide=wide0;//记录下目前已经找到的最小带宽

        string ans=node;//记录下目前已经找到的最优排列

               //遍历后续的排列

        next_permutation(node,node+big);

        do

        {

            wide0=0;//每一组排列都要清空

            int ok=1;

            for(int i=0; i<big; i++)

            {

                int wide1=0;

                for(int j=0; j<big; j++)

                {

                   if(G[node[i]-'A'][node[j]-'A'])

                    {

                        int m=-1,n=-1;

                       while(node[++m]!=node[i]);

                       while(node[++n]!=node[j]);

                       wide1=max(wide1,abs(m-n));

                    }

                }

                wide0=max(wide0,wide1);

                if(wide0>=wide)

// 发现已经有某两个节点的距离大于或等于已经找到的最优解,无需向下寻找

                {

                    ok=0;

                    break;

                }

            }

            if(ok)//如果是自然退出

            {

                wide=wide0;

                ans=node;

            }

        }

        while(next_permutation(node,node+big));

        for(int i=0; i<ans.size(); i++)

        {

            cout<<ans[i]<<"";

        }

        cout<<"->"<<wide<<endl;

    }

    return 0;

}

 

bool check(char u)

{

    for(int i=0; i<strlen(node); i++)

    {

        if(node[i]==u)

        {

            return false;

        }

    }

    return true;

}

 

刘汝佳的代码:

#include<cstdio>

#include<cstring>

#include<vector>

#include<algorithm>

using namespacestd;

 

const int maxn =10;

int id[256],letter[maxn];

 

int main()

{

    char input[1000];

    while(scanf("%s", input) == 1&& input[0] != '#')

    {

        计算结点个数并给字母编号

        int n = 0;

        for(char ch = 'A'; ch <= 'Z'; ch++)

        {

            if(strchr(input, ch) != NULL)

            {

                id[ch] = n++;

                letter[id[ch]] = ch;

            }

        }

        处理输入

        int len = strlen(input), p = 0, q = 0;

        vector<int> u, v;

        for(;;)

        {

            while(p < len &&input[p] != ':')

            {

                p++;

            }

            if(p == len)

            {

                break;

            }

            while(q < len &&input[q] != ';')

            {

                q++;

            }

            for(int i = p+1; i < q; i++)

            {

                u.push_back(id[input[p-1]]);

                v.push_back(id[input[i]]);

            }

            p++;

            q++;

        }

        枚举全排列

        int P[maxn], bestP[maxn], pos[maxn], ans = n;

        for(int i = 0; i < n; i++)

        {

            P[i] = i;

        }

        do

        {

            for(int i = 0; i < n; i++)

            {

                pos[P[i]] = i;

                每个字母的位置

            }

            int bandwidth = 0;

            for(int i = 0; i < u.size();i++)

            {

                bandwidth = max(bandwidth,abs(pos[u[i]] - pos[v[i]]));

                计算带宽

            }

            if(bandwidth < ans)

            {

                ans = bandwidth;

                memcpy(bestP, P, sizeof(P));

            }

        }

        while(next_permutation(P, P+n));

        输出

        for(int i = 0; i < n; i++)

        {

            printf("%c ",letter[bestP[i]]);

        }

        printf("-> %d\n", ans);

    }

    return 0;

}

0 0
原创粉丝点击