• 3149: [Ctsc2013]复原


    3149: [Ctsc2013]复原

    Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special Judge
    Submit: 95  Solved: 44
    [Submit][Status][Discuss]

    Description

    在几何课上,老师画了一个圆,圆上有很多条弦,这些弦两两不重合,但是 有些是相交的。你本想把图临摹下来回家好好研究,可惜下课后,图被值日生 擦掉了。幸运的是,你准确地记录了弦的数量和弦的相交情况。
    现在,你想尽量复原这张图。同时你还想知道,最多能选出多少条弦,使得 选出来的弦两两不相交。

    Input

    第一行包含2个正整数n,m,分别表示弦的条数以及相交弦的对数,所有的弦从1至n编号。接下来 m行每行两个正整数a,b,表示第a条弦与第b条弦相交。

    Output

    输出分为两行。
    第一行输出2n个正整数,按逆时针方向给出满足题意的圆上每条弦的两个
    端点的相对顺序,其中第i条弦的两个端点均用数字i来表示。
    第二行输出1个正整数,表示最多能选多少条两两不相交的弦。

    Sample Input

    5 6
    1 2
    1 3
    2 3
    2 4
    3 5
    4 5

    Sample Output

    1 2 3 1 4 2 5 4 3 5
    2

    HINT

    1<=N<=20 1<=M<=40

    Source

    [
    //表示只会10分暴力
    //对大神的位运算优化膜拜。 
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int N=25;
    const int M=1.5e6+5;
    int n,m,len,cnt,bin[N],lg[M],f[M],q[N],mp[N],pth[N<<1],ans[N<<1];  
    bool a[N][N],vis[N];int sum,end;
    inline void Max(int &x,int y){if(x<y) x=y;}
    bool dfs(int k,int goal){
        if(k>goal) return 1;
        len++;
        for(int i=len;i;i--) pth[i]=pth[i-1];
        for(int i=1;i<=len;i++){
            pth[i]=k;len++;
            for(int j=len;j>i+1;j--) pth[j]=pth[j-1];
            for(int j=i+1,s=0;j<=len;j++){
                pth[j]=k;
                if(!(s^mp[k]) && dfs(k+1,goal)) return 1;
                pth[j]=pth[j+1];
                s^=bin[pth[j]-1];
            }
            len--;pth[i]=pth[i+1];
        }
        len--;
        return 0;
    }
    int bfs(int S){
        int h=0,t=1;len=0;q[t]=S;vis[S]=1;
        while(h!=t){
            int x=q[++h];
            for(int i=1;i<=n;i++){
                if(!vis[i] && a[x][i]){
                    vis[i]=1;
                    q[++t]=i;
                }
            }
        }
        for(int j=1;j<=t;j++){
            mp[j]=0;
            for(int k=1;k<j;k++){
                if(a[q[j]][q[k]]) mp[j]|=bin[k-1];
            }
        }
        return t;
    }
    void work(){
        for(int i=1;i<=len;i++) ans[++cnt]=q[pth[i]];
        for(int i=1;i<=end;i++){
            mp[i]=bin[i-1];
            for(int j=1;j<=end;j++){
                if(a[q[i]][q[j]]){
                    mp[i]|=bin[j-1];
                }
            }
        }
        int mx=0,tot=bin[end]-1;
        memset(f,0,sizeof f);
        for(int j=tot,x;j;j--){
            mx=max(mx,f[j]);
            for(int k=j;k;k^=x){
                x=k&-k;
                Max(f[j&(tot^mp[lg[x]+1])],f[j]+1);
            }
        }
        sum+=max(mx,f[0]);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),a[x][y]=a[y][x]=1;
        for(int i=0;i<=n;i++) bin[i]=1<<i;
        for(int i=2;i<=bin[n];i++) lg[i]=lg[i>>1]+1;
        for(int i=1;i<=n;i++) if(!vis[i]){
            end=bfs(i);
            dfs(1,end);
            work();
        }
        for(int i=1;i<=cnt;i++) printf("%d%c",ans[i],(i<cnt)?' ':'
    ');  
        printf("%d
    ",sum);
        return 0;
    }
  • 相关阅读:
    HDU 5963 朋友
    BZOJ 4805 欧拉函数求和
    BZOJ 2153 设计铁路
    BZOJ 2631 tree
    BZOJ 4804 欧拉心算
    BZOJ 4806 炮
    BZOJ 3774 最优选择
    BZOJ 4800 Ice Hockey World Championship
    BZOJ 3894 文理分科
    北方大学多校联合训练第十一场E:Modules
  • 原文地址:https://www.cnblogs.com/shenben/p/6720066.html
Copyright © 2020-2023  润新知