BNUOJ 39423 暴力,DFS

最有的答案肯定是找到一些点的集合,这些点两两之间是朋友关系。

考虑到n,m比较小,这样的集合最多只有14个点,暴力找点的集合

先找出1 个点的集合,有n个这样的集合

然后找出2个点的集合,找的时候要求编号比之前的大,这样就能保证不重不漏


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cctype>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
typedef long long ll;
using namespace std;
struct node
{
    int tot;
    vector<int> p[11111];
}ji[16];
int n,m;
int Map[110][110];
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(Map,0,sizeof(Map));
        for(int i=0;i<m;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            Map[x][y] = Map[y][x] = z;
        }
        for(int i=0;i<16;i++)
        {
            for(int j=0;j<10010;j++)
                ji[i].p[j].clear();
            ji[i].tot = 0;
        }
        for(int i=1;i<=n;i++)
            ji[0].p[i-1].push_back(i);
        ji[0].tot = n;
        int Max = 0;
        for(int i = 0;i<min(n,14);i++)
        {
            int len = ji[i].tot;
            for(int j = 0;j < len;j++)
            {
                int ss = ji[i].p[j].size();
                int now = ji[i].p[j][ss-1];

                for(int k = now+1;k <= n;k ++ )
                {
                    int flag = 1;
                    for(int s = 0;s < ss;s++)
                        if(Map[k][ ji[i].p[j][s] ] ==0)
                            flag = 0;
                    if(flag)
                    {
                        int Sum  = 0;
                        for(int s = 0;s<ss;s++)
                            ji[i+1].p[ji[i+1].tot].push_back( ji[i].p[j][s]);
                        ji[i+1].p[ji[i+1].tot].push_back(k);

                        int L =  ji[i+1].p[ji[i+1].tot].size();
                        for(int ii = 0;ii<L;ii++)
                        {
                            int Min = 9999999;
                            for(int jj=0;jj<L;jj++)
                                if(ii!=jj)
                                Min = min(Min,Map[ji[i+1].p[ji[i+1].tot][ii]][ji[i+1].p[ji[i+1].tot][jj]]);
                            Sum +=Min;
                        }
                        Max = max(Max,Sum);
                        ji[i+1].tot++;
                    }

                }
            }
        }
//        for(int i=0;i<3;i++)
//            cout<<ji[i].tot<<endl;
        printf("%d\n",Max);
    }
    return 0;
}



DFS写法


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cctype>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
typedef long long ll;
using namespace std;
int Map[111][110];
int s[111];
int cur ;
int n,m;
int Max=  0;
int dfs(int st,int cur)
{
    if(cur>=2)
    {
        int sum = 0;
        for(int i=1;i<=cur;i++)
        {
            int Min  = 99999999;
            for(int j=1;j<=cur;j++)
            if(i!=j)
                Min =  min(Min,Map[s[i]][s[j]]);
            sum+=Min;
        }
        Max = max(sum,Max);
    }
    for(int i = st+1;i <= n;i++)
    {
        int ok = 1;
        for(int j = 1;j<=cur;j++)
        {
            if(Map[i][s[j]]==0)
                ok = 0;
        }
        if(ok)
        {
            s[cur+1] = i;
            dfs(i,cur+1);
        }
    }
    return 0;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=0;i<m;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            Map[x][y]  = Map[y][x] = z;
        }
        Max = 0;
        dfs(0,0);
        printf("%d\n",Max);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值