1. 程式人生 > 實用技巧 >演算法設計例題:最大團(回溯、分枝限界)

演算法設計例題:最大團(回溯、分枝限界)

Description

給定無向圖G=(V,E)。如果UV,且對任意u, v ∈ U 有 (u,v) ∈ E,則稱U是G的完全子圖。G的完全子圖U是G的團,當且僅當U不包含在G的更大的完全子圖中。G的最大團是指G中所含頂點數最多的團。

Input

輸入的第一行為測試樣例的個數T ,接下來有T個測試樣例。每個測試樣例的第一行是 頂點數n 和 邊數m ( n ≤ 20,m ≤ 400 ),接下來m行,每行兩個整數u和v,表示頂點u和v之間有一條邊相連。( 1 ≤ u < v ≤ n )。

Output

對應每個測試樣例輸出兩行,第一行格式為"Case #: M",其中'#'表示第幾個測試樣例(從1開始計),M為最大團頂點數。

Sample Input

1
5 7
1 2
1 4
1 5
2 3
2 5
3 5
4 5

Sample Output

Case 1: 3

深搜做法
#include<bits/stdc++.h>
#define ll long long
const int maxn = 1e3+10;
using namespace std;
bool a[30][30],res;
int n,ans;
vector<int>v;
void solve(int j){
    if(j>n){
        if(ans<v.size())ans=v.size();
        res
=1;return; } bool ss=0; for(int i=0;i<v.size();i++) if(a[j][v[i]]==0){ ss=1;break; } if(!ss){ v.push_back(j); solve(j+1); v.pop_back(); } solve(j+1); } int main() { int t,cas=0;cin>>t; while(t--){ res=0; ans
=0; v.clear(); memset(a,0,sizeof(a)); int m; cin>>n>>m; for(int i=1;i<=m;i++){ int x,y; cin>>x>>y; a[x][x]=a[x][y]=a[y][y]=a[y][x]=1; } solve(1); printf("Case %d: %d\n",++cas,ans); } }

廣搜做法

#include<bits/stdc++.h>
#define pd putchar(' ')
#define pn putchar('\n')
#define pb push_back
#define fi first
#define se second
#define f1(i,j,n) for(int i=j;i<n;i++)
#define f2(i,j,n) for(int i=j;i<=n;i++)
#define mem(i,j) memset(i,j,sizeof(i))
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll long long
#define jiasu ios::sync_with_stdio(false)
#define P1 printf("yes\n")
#define P2 printf("No\n")
const ll mod =1e8+9;
const ll modd=998244353;
const ll maxn = 1e3+10;
const double eps=1e-7;
using namespace std;
struct num{
    int now,res,ans;
};
int a[30][30];
bool solve(int x,int y){
        int countt=0;
        while(x){
            countt++;
            int res=x%2;
            if(res&&!a[y][countt])
                return false;
            x=x>>1;
        }
        return true;
}
int main()
{
    int _,cas=0;scanf("%d",&_);
    while(_--){
        int n,m,ans=0;
        scanf("%d%d",&n,&m);
        f2(i,1,n)
            f2(j,1,n)a[i][j]=0;
        f2(i,1,m){
            int x,y;
            scanf("%d%d",&x,&y);
            a[x][y]=a[y][x]=1;
        }
        queue<num>q;
        q.push({0,0,0});
        while(!q.empty()){
            num temp=q.front();
            q.pop();
            if(temp.now>=n)continue;
            q.push({temp.now+1,temp.res,temp.ans});
            if(solve(temp.res,temp.now+1)){
                temp.res=temp.res|(1<<temp.now);
                temp.ans++;
                ans=ans>temp.ans?ans:temp.ans;
                q.push(temp);
            }
        }
        printf("Case %d: %d\n",++cas,ans);
    }
    return 0;
}