Network Saboteur
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 15961 | Accepted: 7935 |
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
這道題題目不長 看似不難,但是讀不懂題目最致命
題目大意:給你n個點,並通過(鄰接矩陣)給出任意兩點之間的距離,讓你把這n個點分成兩部分A B,目標是讓A中的點到B中所有點的距離之和再求和 最大 ,即求 max(∑(A中的點到B中所有點的距離之和)),確實很饒人,其實這是一個最大割問題
弄懂題意就可以枚舉了,我們先把所有的點放在一個集合裏面,然後逐漸的拿出來組成另一個集合(使用book數組標記),在枚舉的過程中更新所求的最大值,注意交換集合時的數值變換
可以利用一個小剪枝,當加入了一個點使得目標數值變小之後,那麼這個點是不符合要求的,就沒有必要再去枚舉了,其實沒有剪枝也能莽的過去
#include<cstdio>
#include<string>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int _read() {
char ch = getchar();
int sum = 0;
while (!(ch >= '0' && ch <= '9'))ch = getchar();
while (ch >= '0' && ch <= '9')sum = sum * 10 + ch - 48, ch = getchar();
return sum;
}
const int inf=0x3f3f3f3f;
const int mm=22;
int n;
int book[mm];
int mp[mm][mm];
int res;
void dfs(int k,int sum){//枚舉第k個點 當前距離爲sum
int num=sum;
for(int i=1;i<=n;i++)//求出加入k後的sum
if(book[i])
num-=mp[k][i];// 同一個集合 減去
else
num+=mp[k][i];//另一個集合 加上
if(num>res)
res=num;//更新res
for(int i=k+1;i<=n;i++)//嘗試加入其它點
if(num>sum){//小剪枝
book[i]=1;
dfs(i,num);
book[i]=0;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mp[i][j]);
res=-inf;
book[1]=1;
dfs(1,0);
printf("%d\n",res);
return 0;
}