POJ - 2989 All Friends (极大团数量)

All Friends
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 2772 Accepted: 817

Description

Sociologists are interested in the phenomenon of "friendship". To study this property, they analyze various groups of people. For each two persons in such a group they determine whether they are friends (it is assumed that this relation is symmetric). The sociologists are mostly interested in the sets of friends. The set S of people is the set of friends if every two persons in S are friends. However, studying the sets of friends turns out to be quite complicated, since there are too many such sets. Therefore, they concentrate just on the maximal sets of friends. A set of friends S is maximal if every person that does not belong to S is not a friend with someone in S. 

Your task is to determine the number of maximal sets of friends in each group. In case this number exceeds 1 000, you just need to report this -- such a group is too complicated to study. 

Input

The input consists of several instances, separated by single empty lines. 

The first line of each instance consists of two integers 1 ≤ n ≤ 128 and m -- number of persons in the group and number of friendship relations. Each of m following lines consists of two integers ai and bi (1 ≤ ai, bi ≤ n). This means that persons ai and bi (ai ≠ bi) are friends. Each such relationship is described at most once. 

Output

The output for each instance consists of a single line containing the number of maximal sets of friends in the described group, or string "Too many maximal sets of friends." in case this number is greater than 1 000.

Sample Input

5 4
1 2
3 4
2 3
4 5

Sample Output

4

Source


题意:求极大团数量

解题思路:用Bron-Kerbosch算法求极大团数量。推荐博客

把算法看懂后,用代码就很容易实现了。这是我觉得最好的,最易懂的模板了


#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <memory.h>
#include <stack>
#include <string.h>

using namespace std;

int n,m;
int ans;
int G[200][200];
int all[200][200];//第j个极大团所包含的节点
int some[200][200];
int none[200][200];

void dfs(int x,int an,int sn,int nn){
    if(!sn&&!nn){
        ans++;
        //输出极大团
        // for(int i=1;i<=an;i++)
        //     cout<<all[x][i]<<" ";
        // cout<<endl;
    }
    if(ans>1000)
        return;
    
    int key=some[x][1];
    for(int j=1;j<=sn;j++){
        int v=some[x][j];
        int tsn=0;
        int tnn=0;
        
        //剪枝,与key相连的,必被搜索过
        if(G[key][v])
            continue;
        
        for(int i=1;i<=an;i++)
            all[x+1][i]=all[x][i];
        all[x+1][an+1]=v;
        
        for(int i=1;i<=sn;i++)
            if(G[v][some[x][i]])
                some[x+1][++tsn]=some[x][i];
        
        for(int i=1;i<=nn;i++)
            if(G[v][none[x][i]])
                none[x+1][++tnn]=none[x][i];
        
        dfs(x+1,an+1,tsn,tnn);
        
        some[x][j]=0;
        none[x][++nn]=v;
    }
    
}

int main()
{
    
    while(~scanf("%d%d",&n,&m)){
        ans=0;
        memset(G,0,sizeof(G));
        int a,b;
        for(int i=0;i<m;i++){
            scanf("%d%d",&a,&b);
            G[a][b]=1;
            G[b][a]=1;
            
        }
        
        for(int i=1;i<=n;i++)
            some[1][i]=i;
        
        dfs(1,0,n,0);
        
        if(ans > 1000)
            puts("Too many maximal sets of friends.");
        else
            printf("%d\n", ans);
        
        
    }
    
    return 0;
    
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值