poj2531 Network Saboteur

 

Network Saboteur
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 11122   Accepted: 5372

 

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

Source

Northeastern Europe 2002, Far-Eastern Subregion
一道poj搜索简单题。

题意如下:给定一个n*n的方阵描述一个无向带权图,试将改图点集拆分成两个集合使两个集合之间的权值最大。

思路如下:搜索要解决一下两个问题,第一是如何枚举点兵划分入两个集合,第二是如何剪枝优化。首先,要解决n个点的集合归属,直接暴力枚举,用子集枚举的位向量法即可;而对于第二个问题,这里需要一点逆向思维。求集合之间的权值最大,求的其实是每个集合内部那些不能统计的边权值要最小,这样就可以得到转化,答案=边权和-集合内边权和。所以,进行可行性剪枝:若已枚举了所有点,则记录最小值,回溯;同理,进行最优化剪枝:若当前累计边权大小已超过了历史最小值,就剪枝。

15781005

  ksq2013 2531 Accepted 664K 313MS G++ 754B 2016-07-22 11:29:51

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
bool sub[21];
int n,tot,minn=0x3f3f3f3f,w[21][21];
void dfs(int ind,int sum)
{
    if(sum>minn)return;
    if(ind>n){
        minn=sum;
        return;
    }
    int tmp=0;
    sub[ind]=0;
    for(int i=1;i<ind;i++)
        if(!sub[i])
                tmp+=w[ind][i];
    dfs(ind+1,sum+tmp);
    tmp=0;
    sub[ind]=1;
    for(int i=1;i<ind;i++)
        if(sub[i])
            tmp+=w[ind][i];
    dfs(ind+1,sum+tmp);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&w[i][j]);
            tot+=w[i][j];
        }
    }
    dfs(1,0);
    printf("%d\n",tot/2-minn);
    return 0;
}
/*
3
0 50 30
50 0 40
30 40 0
*/


 

posted @ 2016-07-22 11:39  keshuqi  阅读(289)  评论(0编辑  收藏  举报