zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    【洛谷P2927 [USACO08DEC]拼图游戏Jigsaw Puzzles】深搜
    【洛谷1219】 八皇后 (搜索)
    【Uva 12558】 Egyptian Fractions (HARD version) (迭代加深搜,IDA*)
    【转】DCX (数独-八皇后问题)
    【2016 11 14】 总结
    【HDU 3038】 How Many Answers Are Wrong (带权并查集)
    【POJ1182】 食物链 (带权并查集)
    【20161111双11模拟赛】总结
    【HDU 5381】 The sum of gcd (子区间的xx和,离线)
    【HDU 5233】Tree chain problem (树形DP+树剖+线段树|树状数组)最大权不相交树链集
  • 原文地址:https://www.cnblogs.com/mhy12345/p/3859032.html
Copyright © 2011-2022 走看看