覆盖独立集 - dp

题目大意:给你一张无向图 G ( V , E ) , V = n G(V,E),|V|=n ,满足存在整数序列 { a n } \{a_n\} ,使得:
1 x < y n , ( x , y ) V a x > a y \forall1\le x<y\le n,\exist(x,y)\in V\Leftarrow\Rightarrow a_x>a_y
成立。现在问有多少 S V S\subseteq V ,满足:
x , y S , ̸ ( x , y ) E x S , ( x , y ) E y S \forall x,y\in S,\not\exist(x,y)\in E\\\forall x\notin S,\exist(x,y)\in E\Rightarrow y\in S
保证答案小于 2 64 2^{64} n 1 0 3 n\le10^3
题解:
考虑先用差分约束求出任意一个 G ( V , E ) G(V,E) 对应的序列 { a n } \{a_n\} 。考虑
( x , y ) E a m i n ( x , y ) > a m a x ( x , y ) , ( x , y ) E a m i n ( x , y ) a m a x ( x , y ) (x,y)\in E\Leftarrow\Rightarrow a_{min(x,y)}>a_{max(x,y)},(x,y)\notin E\Leftarrow\Rightarrow a_{min(x,y)}\le a_{max(x,y)}
假设 S S 对应的 { a n } \{a_n\} 的子序列是 { b m } \{b_m\} 。问题转为求有多少子序列对应的点集满足条件。
第一个条件其实是在要求 S S G ( V , E ) G(V,E) 的一个独立集,对于序列等价于:
x , y S , x < y , a x a y \forall x,y\in S,x<y,a_x\le a_y
{ b m } \{b_m\} 是一个非降序列。
第二个条件即
x S , y S , a m i n ( x , y ) > a m a x ( x , y ) \forall x\notin S,\exist y\in S, a_{min(x,y)}>a_{max(x,y)}
这等价于:
x S , y S ( y < x a y > a x ) ( y > x a x > a y ) \forall x\notin S,\exist y\in S\Rightarrow(y<x\wedge a_y>a_x)\vee(y>x\wedge a_x>a_y)
由于 { b m } \{b_m\} 是非降序列,二者显然只可能成立一个。
进一步地说,想要让 x S x\notin S 满足条件,只需要考虑其在 S S 中的前驱后继即可。
因此不难发现, { b m } \{b_m\} 合法,当且仅当(记起对应下标为 { c m } \{c_m\} ):
i [ 0 , m ] , b i b i + 1 ( x ( c i , c i + 1 ) , a x ( b i , b i + 1 ) ) \forall i\in[0,m],b_i\le b_{i+1}\wedge \left(\forall x\in(c_i,c_{i+1}),a_x\notin(b_i,b_{i+1}) \right)
并且钦定 c 0 = 0 , c m + 1 = n + 1 , a 0 = inf , a n + 1 = inf c_0=0,c_{m+1}=n+1,a_0=-\inf,a_{n+1}=\inf

d p i dp_i 表示子序列末尾在 i i 的答案,同时维护
d i , j = max k ( j , i ) , a k a i a k d_{i,j}=\max_{k\in(j,i),a_k\le a_i}a_k
最终 d p i = j [ 0 , i ) , a j a i [ a j > d i , j ] d p j dp_i=\sum_{j\in[0,i),a_j\le a_i}[a_j>d_{i,j}]dp_j

时间复杂度 O ( n 2 ) O\left(n^2\right)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define N 1010
#define INF (INT_MAX/10-10)
#define inf (INT_MIN/10+10)
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
    int to,pre,wgt;
}e[N*N];int h[N],etop,g[N][N],a[N],inq[N];ull dp[N];queue<int> q;
inline int add_edge(int u,int v,int w) { return e[++etop].to=v,e[etop].pre=h[u],e[etop].wgt=w,h[u]=etop; }
inline int spfa(int s,int n)
{
    while(!q.empty()) q.pop();
    memset(inq,0,sizeof(int)*(n+1));
    rep(i,1,n) a[i]=-1;
    a[s]=0,q.push(s),inq[s]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop(),inq[x]=0;
        for(int i=h[x],y;i;i=e[i].pre)
            if(a[y=e[i].to]<a[x]+e[i].wgt)
            {
                a[y]=a[x]+e[i].wgt;
                if(!inq[y]) inq[y]=1,q.push(y);
            }
    }
    return 0;
}
int main()
{
    int n=inn(),m=inn(),s=n+1,u,v;
    rep(i,1,m) u=inn()+1,v=inn()+1,g[u][v]=g[v][u]=1;
    rep(i,1,n) rep(j,i+1,n)
        if(g[i][j]) add_edge(j,i,1);
        else add_edge(i,j,0);
    rep(i,1,n) add_edge(s,i,0);
    spfa(s,n+1),a[0]=inf+1,a[n+1]=INF,dp[0]=1;
    rep(i,1,n+1) for(int j=i-1,z=inf;j>=0;j--)
        if(a[j]<=a[i]) { if(z<a[j]) dp[i]+=dp[j];z=max(z,a[j]); }
    return cout<<dp[n+1]<<endl,0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82943466