HDU 6321Problem C. Dynamic Graph Matching(模拟,状压)

题目:给你n个点,m个操作,每种操作要么加一条边要么减一条边,紧接着询问当前选出1条无公共端点的边,2条无公共端点的边,3条.....n/2条无公共端点边时分别有多少种不同的选择。(n<=10) 

思路:真是刺激,比赛时想到了状压没想到怎么搞,然后疯狂算暴力的复杂度。感觉还可以,应该不会T。交了一发,疯狂刷新后结果TLE。然后发现还可以优化下常数,直接把下面的代码写到init里面预处理出4条边和五条边的所有情况,然后ac(3650MS)。     题目只需要考虑新加(减)一条边的影响就可以了,别的方案都在上一步算过了。

状压复杂度O(m*2^n),暴力我算的大约是 常数2*1e3*m,貌似稍微慢一点。。。贴个代码。之后补上状压的。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int t,n,m;
ll a[11][11],ans[10];
vector<int>px[7][11][11],py[7][11][11];
void init(int n)
{
    for(int x=1;x<=n;x++)
    for(int y=x+1;y<=n;y++)
    {
        int nu=0;
        if(n>=8)//4
        {
            int book[11]={0};
            book[x]=book[y]=1;
            for(int i=1;i<=n-5;i++)
            if(!book[i])
            {
                book[i]=1;
                for(int j=i+1;j<=n;j++)
                if(!book[j])
                {
                    book[j]=1;
                    for(int ii=i+1;ii<=n-3;ii++)
                    if(!book[ii])
                    {
                        book[ii]=1;
                        for(int jj=ii+1;jj<=n;jj++)
                        if(!book[jj])
                        {
                            book[jj]=1;
                            for(int iii=ii+1;iii<=n-1;iii++)
                            if(!book[iii])
                            {
                                book[iii]=1;
                                for(int jjj=iii+1;jjj<=n;jjj++)
                                if(!book[jjj])
                                {
                                    nu++;
                                    px[4][x][y].push_back(i);
                                    px[4][x][y].push_back(ii);
                                    px[4][x][y].push_back(iii);

                                    py[4][x][y].push_back(j);
                                    py[4][x][y].push_back(jj);
                                    py[4][x][y].push_back(jjj);
                                   // (ans[4]+=flag*(a[i][j]*a[ii][jj]%mod*a[iii][jjj]%mod)+mod)%=mod;
                                }
                                book[iii]=0;
                            }
                            book[jj]=0;
                        }
                        book[ii]=0;
                    }
                    book[j]=0;
                }
                book[i]=0;
            }
        }
       // cout<<nu<<endl;
       // cout<<uu<<endl;
        if(n>=10)//5
        {
            int book[11]={0};
            book[x]=book[y]=1;
            for(int i=1;i<=n-7;i++)
            if(!book[i])
            {
                book[i]=1;
                for(int j=i+1;j<=n;j++)
                if(!book[j])
                {
                    book[j]=1;
                    for(int ii=i+1;ii<=n-5;ii++)
                    if(!book[ii])
                    {
                        book[ii]=1;
                        for(int jj=ii+1;jj<=n;jj++)
                        if(!book[jj])
                        {
                            book[jj]=1;
                            for(int iii=ii+1;iii<=n-3;iii++)
                            if(!book[iii])
                            {
                                book[iii]=1;
                                for(int jjj=iii+1;jjj<=n;jjj++)
                                if(!book[jjj])
                                {
                                    book[jjj]=1;
                                    for(int i4=iii+1;i4<=n-1;i4++)
                                    if(!book[i4])
                                    {
                                        book[i4]=1;
                                        for(int j4=i4+1;j4<=n;j4++)
                                        if(!book[j4])
                                        {
                                            px[5][x][y].push_back(i);
                                            px[5][x][y].push_back(ii);
                                            px[5][x][y].push_back(iii);
                                            px[5][x][y].push_back(i4);

                                            py[5][x][y].push_back(j);
                                            py[5][x][y].push_back(jj);
                                            py[5][x][y].push_back(jjj);
                                            py[5][x][y].push_back(j4);
                                        }
                                        book[i4]=0;
                                    }
                                    book[jjj]=0;
                                }
                                book[iii]=0;
                            }
                            book[jj]=0;
                        }
                        book[ii]=0;
                    }
                    book[j]=0;
                }
                book[i]=0;
            }
        }
    }
    //cout<<px[4][1][5].size()<<endl;
    //cout<<px[5][1][2].size()<<endl;
}
int main()
{
    scanf("%d",&t);
    init(10);
    while(t--)
    {
        memset(a,0,sizeof a);
        memset(ans,0,sizeof ans);
        scanf("%d%d",&n,&m);
        while(m--)
        {
            char s[2];
            int x,y;
            scanf("%s%d%d",s,&x,&y);
            ll flag=(s[0]=='+'?1:-1);
            if(x>y) swap(x,y);
            a[x][y]+=flag;
            ans[1]+=flag;///1
            if(n>=4)///2
            {
                for(int i=1;i<=n-1;i++)
                if(i!=x&&i!=y)
                {
                    for(int j=i+1;j<=n;j++)
                    if(j!=x&&j!=y)
                        (ans[2]+=flag*a[i][j]+mod)%=mod;
                }
            }
            int nn=0;
            if(n>=6)///3
            {
                int book[11]={0};
                book[x]=book[y]=1;
                for(int i=1;i<=n-3;i++)
                if(!book[i])
                {
                    book[i]=1;
                    for(int j=i+1;j<=n;j++)
                    if(!book[j])
                    {
                        book[j]=1;
                        for(int ii=i+1;ii<=n-1;ii++)
                        if(!book[ii])
                        {
                            book[ii]=1;
                            for(int jj=ii+1;jj<=n;jj++)
                            if(!book[jj])
                            {
                                nn++;
                                (ans[3]+=flag*(a[i][j]*a[ii][jj]%mod)+mod)%=mod;
                            }
                            book[ii]=0;
                        }
                        book[j]=0;
                    }
                    book[i]=0;
                }
            }
           // cout<<nn<<endl;
            if(n>=8)
            {
                for(int i=0;i<px[4][x][y].size();i+=3)
                {
                    int i1=px[4][x][y][i];
                    int i2=px[4][x][y][i+1];
                    int i3=px[4][x][y][i+2];
                    int j1=py[4][x][y][i];
                    int j2=py[4][x][y][i+1];
                    int j3=py[4][x][y][i+2];
                    (ans[4]+=flag*(a[i1][j1]*a[i2][j2]%mod*a[i3][j3]%mod)+mod)%=mod;
                }
            }
            if(n>=10)
            {
                for(int i=0;i<px[5][x][y].size();i+=4)
                {
                    int i1=px[5][x][y][i];
                    int i2=px[5][x][y][i+1];
                    int i3=px[5][x][y][i+2];
                    int i4=px[5][x][y][i+3];

                    int j1=py[5][x][y][i];
                    int j2=py[5][x][y][i+1];
                    int j3=py[5][x][y][i+2];
                    int j4=py[5][x][y][i+3];
                    (ans[5]+=flag*(a[i1][j1]*a[i2][j2]%mod*a[i3][j3]%mod*a[i4][j4]%mod)+mod)%=mod;
                }
            }
            for(int i=1;i<=n/2;i++)
            {
                if(i<n/2)
                printf("%d ",ans[i]);
                else printf("%d\n",ans[i]);
            }
        }
    }
    return 0;
}

好长的代码,下面是状压的做法(3478MS),dp[i][s]表示到达i步,用s状态的点时,有多少种方案。状压就不用考虑具体的匹配是什么样子的啦。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll dp[2][1<<10],ans[11];
int t,n,m;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(dp,0,sizeof dp);
        dp[0][0]=1;
        for(int i=1;i<=m;i++)
        {
            int x,y; char str[2];
            scanf("%s%d%d",str,&x,&y);
            x--,y--;
            ll flag=(str[0]=='+')?1:-1;
            for(int s=0;s<(1<<n);s++)
            {
                dp[i&1][s]=dp[(i-1)&1][s];
                if((s&(1<<x))&&(s&(1<<y)))
                    (dp[i&1][s]+=flag*dp[(i-1)&1][s^(1<<x)^(1<<y)]+mod)%=mod;
            }
            memset(ans,0,sizeof ans);
            for(int s=0;s<(1<<n);s++)
            {
                int k=__builtin_popcount(s);
                (ans[k]+=dp[i&1][s])%=mod;
            }
            printf("%lld",ans[2]);
            for(int i=4;i<=n;i+=2)
                printf(" %lld",ans[i]);
            puts("");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dllpXFire/article/details/81291193