• BZOJ 3037 创世纪


    我勒个去怎么这么长。。。。。

    求基环森林的最小点覆盖。注意这里是有向的。那么我们考虑加不加多的那条边,对每个连通块dp两遍就行了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define maxv 1000050
    #define inf 1000000007
    using namespace std;
    int n,a[maxv],dx[maxv],dy[maxv],pos[maxv],dp[maxv][3],cnt=0,father[maxv],ans=0;
    bool flag[maxv];
    struct pnt
    {
        int id,father,rank;
    }p[maxv];
    struct edge
    {
        int x,y,father,root;
    }e[maxv];
    queue <int> q;
    int read()
    {
        char ch;int data=0;
        while (ch<'0' || ch>'9') ch=getchar();
        while (ch>='0' && ch<='9') 
        {
            data=data*10+ch-'0';
            ch=getchar();
        }
        return data;
    }
    bool cmp1(pnt x,pnt y)
    {
        if (x.father!=y.father) return x.father<y.father;
        return x.rank<y.rank;
    }
    bool cmp2(edge x,edge y) {return x.father<y.father;}
    int getfather(int x)
    {
        if (father[x]==x) return x;
        father[x]=getfather(father[x]);return father[x];
    }
    void topu_sort()
    {
        for (int i=1;i<=n;i++)
        {
            if (!dy[i]) q.push(i);
            p[i].father=getfather(i);
        }
        while (!q.empty())
        {
            int head=q.front();q.pop();
            dy[a[head]]--;if (!dy[a[head]]) {p[a[head]].rank=p[head].rank+1;q.push(a[head]);}
        }
        sort(p+1,p+n+1,cmp1);sort(e+1,e+cnt+1,cmp2);
    }
    void tree_dp(int x,int l,int r)
    {
        for (int i=l;i<=r;i++) {pos[p[i].id]=inf;flag[p[i].id]=false;dp[p[i].id][1]=dp[p[i].id][2]=0;}
        int i;dp[0][1]=dp[0][2]=inf;
        for (i=l;!p[i].rank;i++)
        {
            int v=p[i].id;
            if (v!=x) dp[v][1]=inf;else dp[v][1]=0;dp[v][2]=1;
            if (v!=a[v])
            {
                if (dp[v][1]<dp[v][2]) {dp[a[v]][1]+=dp[v][1];pos[a[v]]=min(pos[a[v]],dp[v][2]-dp[v][1]);}
                else {dp[a[v]][1]+=dp[v][2];flag[a[v]]=true;}
                dp[a[v]][2]+=min(dp[v][1],dp[v][2]);
            }
            dp[v][1]=min(dp[v][1],inf);dp[v][2]=min(dp[v][2],inf);
        }
        for (;i<=r;i++)
        {
            int v=p[i].id;
            if ((v!=x) && (!flag[v])) dp[v][1]+=pos[v];dp[v][2]++;
            if (v!=a[v])
            {
                if (dp[v][1]<dp[v][2]) {dp[a[v]][1]+=dp[v][1];pos[a[v]]=min(pos[a[v]],dp[v][2]-dp[v][1]);}
                else {dp[a[v]][1]+=dp[v][2];flag[a[v]]=true;}
                dp[a[v]][2]+=min(dp[v][1],dp[v][2]);
            }
            dp[v][1]=min(dp[v][1],inf);dp[v][2]=min(dp[v][2],inf);
        }
    }
    int main()
    { 
        n=read();for (int i=1;i<=n;i++) {father[i]=i;p[i].id=i;}
        for (int i=1;i<=n;i++)
        {
            a[i]=read();
            int f1=getfather(i),f2=getfather(a[i]);
            if (f1==f2) {e[++cnt].x=i;e[cnt].y=a[i];}
            else {dx[i]++;dy[a[i]]++;father[f1]=f2;}
        }
        for (int i=1;i<=cnt;i++) e[i].father=getfather(e[i].x); 
        topu_sort();
        int l=1,r=1,ret=0;
        while (l<=n)
        {
            int mn=inf;r=l;while (p[r+1].father==p[l].father) r++;
            int i;ret++;
            tree_dp(-1,l,r);mn=min(mn,min(dp[e[ret].x][1],dp[e[ret].y][2]));
            tree_dp(e[ret].y,l,r);mn=min(mn,dp[e[ret].x][2]);
            ans+=mn;l=r+1;
        }
        printf("%d
    ",n-ans);
        return 0;
    }
  • 相关阅读:
    mybatis设置select返回HashMap,字段值为null时,不会保存key
    copyProperties 忽略null值字段
    动态新增表单
    页面时时刷新数据
    FormData 传List对象集合到后台
    linux常用命令总结
    Linux部署安装JDK
    yum安装nginx
    01_Python基础
    Nginx防盗链
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6576608.html
Copyright © 2020-2023  润新知