POJ2531---Network Saboteur(dfs)

                                                      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;
}

 

發佈了84 篇原創文章 · 獲贊 15 · 訪問量 3637
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章