您现在的位置是:首页 > web开发 > Network Saboteur (DFS)

Network Saboteur (DFS)

web开发作者:dayu日期:5天前点击:2

题目:

A university network is composed of N computers. System administrators gathered information on the traffic between nodes, and carefully divided the network into two subnetworks in order to minimize traffic between parts.
A disgruntled computer science student Vasya, after being expelled from the university, decided to have his revenge. He hacked into the university network and decided to reassign computers to maximize the traffic between two subnetworks.
Unfortunately, he found that calculating such worst subdivision is one of those problems he, being a student, failed to solve. So he asks you, a more successful CS student, to help him.
The traffic data are given in the form of matrix C, where Cij is the amount of data sent between ith and jth nodes (Cij = Cji, Cii = 0). The goal is to divide the network nodes into the two disjointed subsets A and B so as to maximize the sum ∑Cij (i∈A,j∈B).

Input

The first line of input contains a number of nodes N (2 <= N <= 20). The following N lines, containing N space-separated integers each, represent the traffic matrix C (0 <= Cij <= 10000).
Output file must contain a single integer -- the maximum traffic between the subnetworks.

Output

Output must contain a single integer -- the maximum traffic between the subnetworks.

Sample Input

3
0 50 30
50 0 40
30 40 0

Sample Output

90

题意:
这个题目看了好久,都不知道在讲个什么东西,百度也弄了好久,终于找到了有很好解析的解题报告;
我理解的大概就是这个意思啦!
输入一个数代表子网的数量;
例如:题目例子为3
1 2 3
1 0 50 30
2 50 0 40
3 30 40 0
总共有3个子网,第1个子网和第2个子网之间的通信量为50,第1个子网与第3个子网之间的通信量为30;
就是这个意思差不多了!!!
题目要求的是让你把这3个子网分为两个部分,使得通信量最大;
还是上面这个例子:
通信量最大的情况是把1,2,3三个子网分为{1,3}和{2};
即子网2和子网1,3之间的通信量是最大的
num_max=map[1][2]+map[3][2];
num_max=90;
我刚开始以为就只有三个子网,以为将每一行想相加就能得到最大值(笑cry),后来发现是20以内的子网数量;
那就需要用DFS啦!(看解析看了好久才理解怎么写)
那我们一开始就将所有的子网都放在一个集合中,另外一个是空的;

AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int map[25][25];
int f[25];
int n;
int num_max;
void dfs(int num,int sum)
{
    f[num]=1;      //做个标记,好知道我把谁扔空集合里面了
    int total=sum;     // sum之前的,total是处理之后的
    for (int i=1;i<=n;i++)
    {
        if (f[i]==1)
        total-=map[num][i];    //与num在一个集合里面,减去权值
        else
        total+=map[num][i];    //与num不在一个集合里面的,加上权值
    }
    num_max=num_max>total?num_max:total;    //取最大值
    for (int i=num+1;i<=n;i++)
    {
        if (total>sum)
        {
          dfs(i,total);       //这个我理解的是:比如我输入4,集合就会有{1,2},{1,3},{1,4},{2,3},{2,4},{3,4},{1,2,3},{4},{1,2,4},{3},{2,3,4},{1},{1,3,4},{2}
            f[i]=0;           // 像第一次DFS时,num=1;这时第一个i取2,就会有{1,2}和{3,4}集合,
        }                     //循环完第一次以后,f[0]=0,就是讲我倒回来把2从新集合中踢出去,i=3,把3丢进来,循环往复
    }
}
int main()
{
    while (scanf("%d",&n)==1)
    {
        memset(f,0,sizeof(f));
         for (int i=1;i<=n;i++)
       for (int j=1;j<=n;j++)
            cin>>map[i][j];
            num_max=-10000;
          dfs(1,0);     //将1放入到空集合中
    cout << num_max << endl;
    }

    return 0;
}

觉得好难啊!!!主要是没怎么接触过递归!!!看了好久才理清楚的思路!!!

Network Saboteur (DFS)

原文地址:http://www.cnblogs.com/lisijie/p/7241478.html


下一篇       上一篇