POJ - 2531 Network Saboteur

探讨如何通过重新分配大学网络中的计算机节点,来最大化两个子网络间的通信流量。面对这一挑战,采用深度搜索回溯算法遍历所有可能的节点组合,以找出最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Network Saboteur

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 15496 Accepted: 7667

Description

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

【题意】

给出n个点,map[i][j]表示第i个点到第j个点的权值,把这些点分为两个部分,使这两部分之间的权值和最大。

【思路】

深搜遍历回溯,一开始定义一个vis[21]数组,全部为0,取出一个cur标记为1,即把这个点放在另一个集合里,对于和cur在一个集合里的点,减去他们之间的权值;不在一个集合里的点,加上他们之间的权值,遍历每一个点,最后的结果为最大值。

AC代码

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int dp[21][21];
int vis[21];
int n,ans;
void dfs(int cur,int cost)
{
     vis[cur]=1;//取出点
     int tmp=cost;
     for(int i=0;i<n;++i)
     {
         if (!vis[i])  //如果不在一个集合,就加上它们之间的权值
            tmp+=dp[cur][i];
         else             //如果在一个集合,减去之间的权值
            tmp-=dp[cur][i];
     }
     if(tmp>ans) //循环结束找到最大值
        ans=tmp;
     if(tmp>cost) //如果加入了cur以后两个集合之间的权值小了,就不需要搜了
     for(int i=cur+1;i<n;++i)//搜剩下的点
     {
         dfs(i,tmp);
         vis[i]=0;
     }
}
int main()
{
    while(cin>>n)
    {
          for(int i=0;i<n;++i)
              for(int j=0;j<n;++j)
              cin>>dp[i][j];
          memset(vis,0,sizeof(vis));
          ans=0;
          dfs(0,0);
         cout<<ans<<endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值