bzoj 3632: 外太空旅行 最大团

3632: 外太空旅行

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 389  Solved: 129
[Submit][Status]

Description

在人类的触角伸向银河系的边缘之际,普通人上太空旅行已经变得稀松平常了。某理科试验班有n个人,现在班主任要从中选出尽量多的人去参加一次太空旅行活动。
可 是n名同学并不是和平相处的。有的人,比如小A和小B整天狼狈为奸,是好朋友;但还有的人,比如杜鲁门和赫鲁晓夫就水火不相容。这n名同学,由于是理科 生,都非常的理性,所以“朋友的朋友就是朋友”和“敌人的朋友就是敌人”这两句话对这些同学无效。换句话说,有可能小A和小B是朋友,小B和小C是朋友, 但是小A和小C两人势如水火。
任意两个人之间要不就是敌人,要不就是朋友。
因为在太空船上发生人员斗殴事件是很恶劣也很危险的,因此选出来参加旅行活动的同学必须互相之间都是朋友。你的任务就是确定最多可以选多少人参加旅行。
 

Input

第一行一个整数n(1<=n<=50)。所有的同学按照1~n编号。
接下来若干行,每行两个用空格隔开的整数a, b(1<=a,b<=n),表示a和b是朋友。
注意:如果一个数对(x,y)(或者(y,x))没有在文件中出现,那么编号为x和y的两个同学就是敌人。
 

Output

仅仅一个数,即最多可以选多少人参加活动。
 

Sample Input

4
1 2
2 3
3 1
1 4

Sample Output

3
说明:选编号为1,2,3的同学参加,他们互相都是朋友。

HINT

Source

最大团在考试的时候用随机化+贪心正确性还是很高的,而且能轻而易举拓展到n=200及以上。

而DFS算法则可以看做是dfs优化的经典题目。

算法传送门:http://www.cnblogs.com/zhj5chengfeng/archive/2013/07/29/3224092.html

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 102
#define MAXM 100000
int e[2][MAXM][2];
int map[MAXN][MAXN];
int q[MAXN],topq;
int next[MAXN];
int n,m;
int work()
{
        topq=0;
        q[0]=0;
        int i,j;
        bool flag;
        for (i=1;i<n;i++)
        {
                flag=true;
                for (j=0;j<=topq;j++)
                {
                        if (!map[i][q[j]])
                        {
                                flag=false;break;
                        }
                }
                if (flag)
                {
                        q[++topq]=i;
                }
        }
        return topq+1;
}
int main()
{
        freopen("input.txt","r",stdin);
//      freopen("output.txt","w",stdout);
        scanf("%d",&n);
        int i,j,k;
        int x,y,z;
        i=0;
        while (~scanf("%d%d",&e[1][i][0],&e[1][i][1]))
        {
                e[1][i][0]--;
                e[1][i][1]--;
                if (map[e[1][i][0]][e[1][i][1]])continue;
                m++;
                i++;
        }
        int ans=0;
        int cnt=0;
        while (cnt++<20000)
        {
                memset(map,0,sizeof(map));
                for (i=0;i<m;i++)
                {
                        map[e[cnt&1][i][0]][e[cnt&1][i][1]]=map[e[cnt&1][i][1]][e[cnt&1][i][0]]=true;
                }
                ans=max(ans,work());
                for (i=0;i<n;i++)
                        next[i]=i;
                for (i=0;i<n;i++)
                {
                        x=rand()%n;
                        y=rand()%n;
                        swap(next[x],next[y]);
                }
                for (i=0;i<m;i++)
                {
                        for (j=0;j<2;j++)
                        {
                                e[cnt&1^1][i][j]=next[e[cnt&1][i][j]];
                        }
                }
        }
        printf("%d
",ans);
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 102 
#define MAXM 100000
int e[MAXM][2];
int map[MAXN][MAXN];
int n,m;
int s[MAXN][MAXN];
int tops[MAXN];
int l[MAXN],topl=-1;
int ans=0;
int rec[MAXN];
int dfs(int lev)
{
        int i,j;
        int x;
        if (lev>ans)
        {
                ans=lev;
                return 1;
        }
        if (lev+tops[lev]+1<=ans)return 0;
        for (i=0;i<=tops[lev];i++)
        {
                x=s[lev][i];
                tops[lev+1]=-1;
                if (i<tops[lev]&&lev+1+rec[s[lev][i+1]]<=ans)return 0;
                for (j=i;j<=tops[lev];j++)
                {
                        if (map[x][s[lev][j]])s[lev+1][++tops[lev+1]]=s[lev][j];
                }
                l[lev]=x;
                if (dfs(lev+1))return 1;
        }
        return 0;
}
int main()
{
        freopen("input.txt","r",stdin);
           //freopen("output.txt","w",stdout);
        scanf("%d",&n);
        int i,j,k;
        int x,y,z;
        i=0;
        while (~scanf("%d%d",&e[i][0],&e[i][1]))
        {
                e[i][0]--;
                e[i][1]--;
                m++;
                i++;
        }
        int cnt=0;
        memset(map,0,sizeof(map));
        for (i=0;i<m;i++)
        {
                map[e[i][0]][e[i][1]]=map[e[i][1]][e[i][0]]=true;
        }
        for (i=n-1;i>=0;i--)
        {
                for (j=i;j<n;j++)
                        s[0][j-i]=j;
                tops[0]=n-i-1;
                dfs(0);
                rec[i]=ans;
        //        cout<<i<<endl;
        }
        printf("%d
",ans);
}
by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

本博客已停用,新博客地址:http://mhy12345.xyz

原文地址:https://www.cnblogs.com/mhy12345/p/3859032.html