BZOJ 3037 创世纪

来源:互联网 发布:ssm log4j sql 编辑:程序博客网 时间:2024/05/17 00:16

给定有向图,每个点仅有一条出边,取的点至少存在一个不去的点指向它,求最多取点数。
n106

遇见MirrorGray

难度应该和 BZOJ 1040 [ZJOI2008]骑士 差不多,流行的是两种做法:拓扑排序+贪心或者转化成求最小支配集,但鉴于多校#4 HDU 5331 Simple Problem 的影响,我觉得可以把问题转化成求最大匹配数。
还没A,而且从已有的提交来看一组数据都没过,btw,我的答案偏大,这就让我很费解了,和PoPoQQQ的程序对拍一晚都没事,只能说BZOJ数据真强
如果A了,就可以得到一个好像没什么用的结论:n=最大匹配数+最小支配数。
再耗下去要出事,就这样吧。

毛主席:牢骚太盛防肠断 风物长宜放眼量。

晚安++

#include<cstdio>#include<cstring>#include<iostream>#include<cassert>#include<algorithm>#define fi first#define se second#define inf (1<<30)#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;typedef pair<int,int> ii;template<class T>void sc(T &x){    int f=1;x=0;char c;    while(c=getchar(),c<48)if(c=='-')f=-1;    do x=x*10+(c^48);    while(c=getchar(),c>47);    x*=f;}template<class T>void nt(T x){    if(!x)return;    nt(x/10);    putchar('0'+x%10);}template<class T>void pt(T x){    if(x<0){        putchar('-');        x=-x;    }    if(!x)putchar('0');    else nt(x);}//----------------------------const int maxn=1000005;int n;int last[maxn],ecnt;struct abcd{    int to,nxt;}edge[maxn<<1];void ins(int x,int y){    edge[++ecnt]=(abcd){y,last[x]};    last[x]=ecnt;}int dp[2][maxn];bool ban[maxn];ii loop[maxn];int top;int fa[maxn];int get(int x){    return fa[x]==x?x:fa[x]=get(fa[x]);}void treedp(int x,int f){    dp[0][x]=0;    dp[1][x]=-inf;    for(int i=last[x];i;i=edge[i].nxt){        int to=edge[i].to;        if(to!=f){            treedp(to,x);            int v=max(dp[0][to],dp[1][to]);            dp[0][x]+=v;            if(!ban[to])//能支配的点                 dp[1][x]=max(dp[1][x],dp[0][to]-v);        }    }    if(ban[x]||dp[1][x]==-inf)dp[1][x]=0;//不能支配别的点     else dp[1][x]=dp[0][x]+dp[1][x]+1;}int main(){//  freopen("pro.in","r",stdin);//  freopen("pro.out","w",stdout);    sc(n);    for(int i=1;i<=n;i++)fa[i]=i;    for(int u,i=1;i<=n;i++){        sc(u);        if(get(u)==get(i))            loop[++top]=ii(u,i);        else{            fa[get(u)]=get(i);            ins(u,i);            ins(i,u);        }    }    int res=0;    for(int i=1;i<=top;i++){        int ans=0;        int x=loop[i].fi,y=loop[i].se;        treedp(x,0);        ans=dp[1][x];        ban[y]=true;        ban[x]=true;        treedp(x,0);        ans=max(ans,dp[0][x]+1);        res+=ans;    }    pt(res);    return 0;}
0 0