百度之星复赛T6&&hd6149 ——Valley Numer II

Problem Description

众所周知,度度熊非常喜欢图。

它最近发现了图中也是可以出现 valley —— 山谷的,像下面这张图。

为了形成山谷,首先要将一个图的顶点标记为高点或者低点。标记完成后如果一个顶点三元组<X, Y, Z>中,X和Y之间有边,Y与Z之间也有边,同时X和Z是高点,Y是低点,那么它们就构成一个valley。

度度熊想知道一个无向图中最多可以构成多少个valley,一个顶点最多只能出现在一个valley中。

Input

第一行为T,表示输入数据组数。

每组数据的第一行包含三个整数N,M,K,分别表示顶点个数,边的个数,标记为高点的顶点个数。

接着的M行,每行包含两个两个整数Xi,Yi,表示一条无向边。

最后一行包含K个整数Vi,表示这些点被标记为高点,其他点则都为低点。

● 1≤T≤20

● 1≤N≤30

● 1≤M≤N*(N-1)/2

● 0≤K≤min(N,15)

● 1≤Xi, Yi≤N, Xi!=Yi

● 1≤Vi≤N

Output

对每组数据输出最多能构成的valley数目。

Sample Input
3
3 2 2
1 2
1 3
2 3
3 2 2
1 2
1 3
1 2
7 6 5
1 2
1 3
1 4
2 3
2 6
2 7
3 4 5 6 7
Sample Output
1
0
2
——————————————————————————————————————————————————————————
果然状压dp不是很熟悉 比赛的时候没有想出来
f【i】【j】表示前i块石头 j及高点的情况
然后枚举两个高点就好辣
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=107,maxn=100010;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
int T,n,m,k,now,ans,cnt;
int h[M],v[M];
int f[2][maxn],map[M][M];
void clear(){
    ans=0; cnt=1;
    memset(map,0,sizeof(map));
    memset(f,0,sizeof(f));
    memset(v,0,sizeof(v));
}
int main()
{
    T=read();
    while(T--){
        int x,y;
        n=read(); m=read(); k=read();
        clear();
        for(int i=1;i<=m;i++) x=read(),y=read(),map[x][y]=map[y][x]=1;
        for(int i=1;i<=k;i++) h[i]=read(),v[h[i]]=1;
        int s=(1<<k)-1;
        for(int i=1;i<=n;i++)if(!v[i]){
            now=(++cnt)&1;
            memset(f[now],0,sizeof(f[now]));
            for(int j=0;j<=s;j++) f[now][j]=f[now^1][j];
            for(int j=0;j<=s;j++){ 
                for(int k1=1;k1<=k;k1++) if(!(j&(1<<(k1-1)))&&map[i][h[k1]]){
                    for(int k2=k1+1;k2<=k;k2++) if(!(j&(1<<(k2-1)))&&map[i][h[k2]]){
                        int nows=j^(1<<(k1-1))^(1<<(k2-1));
                        f[now][nows]=max(f[now][nows],f[now^1][j]+1);
                    }
                } 
            }
        }
        for(int i=0;i<=s;i++) ans=max(ans,f[now][i]);
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 


posted @ 2017-08-18 20:58  友人Aqwq  阅读(259)  评论(0编辑  收藏  举报