题目链接:
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2306
题意:
给定n个点的完全图,下面给出m条边权不为0的边
下面m行给出边和边权。
其他的边边权都为0.
选择一个点集出来,点权是这个点连接这个点集的边权最小值
找一个这样的子图使得点权和最大,输出点权和。
题解:
最后选出来的点,一定是由那m个边所组成的完全图
因为是一个完全图,所以我们选择的点构成的图一定不包含权值为0的边。因为若包含了权值为0的边,则大可以把这两点删掉而不会减小答案。
所以我们选择的图中的边一定只 包含给出的m条边,且由这m条边构成的一个团。
只有100个边,所以最多就是14个点的完全图
即 n*(n-1)/2 <= 100 => n <=14
所以爆搜这14个点就可以了
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define MS(a) memset(a,0,sizeof(a)) 5 #define MP make_pair 6 #define PB push_back 7 const int INF = 0x3f3f3f3f; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 9 inline ll read(){ 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 ////////////////////////////////////////////////////////////////////////// 16 const int maxn = 1e5+10; 17 18 int n,m,mp[105][105],vis[105],ans; 19 vector<int> Q; 20 21 void dfs(int u){ 22 int tmp = 0; 23 for(int i=0; i<(int)Q.size(); i++){ 24 int minn = INF; 25 for(int j=0; j<(int)Q.size(); j++){ 26 if(i!=j) minn = min(minn,mp[Q[i]][Q[j]]); 27 } 28 if(minn == INF) 29 minn = 0; 30 tmp += minn; 31 } 32 ans = max(ans,tmp); 33 34 for(int v=u+1; v<=n; v++){ 35 if(vis[v]) continue; 36 int flag = 1; 37 for(int j=0; j<(int)Q.size(); j++){//如果v没有与当前选的点集有权边,v就一定不在要选的点集中 38 if(mp[v][Q[j]] == 0) { 39 flag = 0; 40 break; 41 } 42 } 43 44 if(flag){ 45 vis[v] = 1; // 选v 46 Q.push_back(v); 47 dfs(v); 48 vis[v] = 0; // 不选v 因为 选v可能使得答案变小 49 Q.pop_back(); 50 } 51 } 52 } 53 54 int main(){ 55 n=read(), m=read(); 56 for(int i=0; i<m; i++){ 57 int u,v,w; scanf("%d%d%d",&u,&v,&w); 58 mp[u][v]=mp[v][u]=w; 59 } 60 61 for(int i=1; i<=n; i++){ 62 vis[i] = 1; 63 Q.push_back(i); // 枚举肯定选哪个点的情况 64 dfs(0); 65 Q.pop_back(); 66 vis[i] = 0; 67 } 68 69 cout << ans << endl; 70 71 return 0; 72 }