zoukankan      html  css  js  c++  java
  • 一题多解——Strategic Game

    点击打开题目

    题目大意:给定一棵无根树,点亮其中某些点,使得这棵树的所有边都连接着一个以上的点亮的点

    贪心中比较有挑战的题
    由于如果点亮叶节点,就只会照亮一条边,但点亮它的父亲,就可以照亮除此边以外的更多的边,所以,可先将所有叶节点的父亲点亮
    其余的点,则通过后序遍历来访问,如果它的所有儿子都点亮了,那它就不用点亮,反之则点亮它,最后在搜索出所有点亮的点的数量即可

    代码如下:

    #include <cstdio>
    #include<cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int fir[3001],nxt[3001],to[3001],cnt;
    bool vis[1501],lt[1501];
    int getint()
    {
        int num=0,flag=1;char c;
        while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
        while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
        return num*flag;
    }
    void newnote(int u,int v){to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    int n,ans;
    void dfs(int x)
    {
        int i;
        for(i=fir[x];i;i=nxt[i])
            if(!vis[to[i]])
            {
                vis[to[i]]=1;
                dfs(to[i]);
                if(!lt[to[i]])lt[x]=1;
            }
    }
    int main()
    {
        int i,j,x,y;
        while(scanf("%d",&n)==1)
        {
            ans=cnt=0;
            memset(fir,0,sizeof fir);memset(to,0,sizeof to);memset(nxt,0,sizeof nxt);
            memset(vis,0,sizeof vis);memset(lt,0,sizeof lt);
            for(i=1;i<=n;i++)
            {
                x=getint()+1;j=getint();
                while(j--)y=getint()+1,newnote(x,y),newnote(y,x);
            }
            dfs(1);
            for(i=1;i<=n;i++)if(lt[i])ans++;
            printf("%d
    ",ans);
        }
    }

    如果没有yy到这种方法,树形DP也可以
    dp[root][0]为没有点亮,dp[root][1]为点亮
    状态转移方程如下:
    dp[root][0]+=dp[son[root][i]][1];
    dp[root][1]+=min(dp[son[root][i]][0],dp[son[root][i]][1]);

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int dp[1501][2],son[1500][1500],fa[1501];
    int min(int x,int y){return x<y?x:y;}
    int getint()
    {
        char c;int flag=1,num=0;
        while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
        while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
        return num*=flag;
    }
    void work(int root)
    {
        int i;
        for(i=1;i<=son[root][0];i++)
        {
            work(son[root][i]);
            dp[root][0]+=dp[son[root][i]][1];
            dp[root][1]+=min(dp[son[root][i]][0],dp[son[root][i]][1]);
        }
        dp[root][1]++;
    }
    int n;
    int main()
    {
        int i,j,x,y,z;
        n=getint();
        for(i=1;i<=n;i++)
        {
            x=getint(),x++,y=getint();
            for(j=1;j<=y;j++)
            {
                z=getint(),z++;
                son[x][++son[x][0]]=z;
                fa[z]=x;
            }
        }
        for(i=1;i<=n;i++)
            if(!fa[i])
            {
                work(i);
                printf("%d",min(dp[i][0],dp[i][1]));
            }
    }

    DP也yy不到?看二分图匹配能不能救你

    代码如下:

    #include <cstdio>
    #include<cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int fir[3001],nxt[3001],to[3001],cnt;
    bool vis[1501],vy[3001];
    int linky[3001],X[1501],g;
    int getint()
    {
        int num=0,flag=1;char c;
        while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
        while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
        return num*flag;
    }
    void newnote(int u,int v){to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    int n,ans;
    void dfs(int u,int deep)
    {
        int i;
        if(deep&1)X[++g]=u;
        for(i=fir[u];i;i=nxt[i])
            if(!vis[to[i]])
            {
                vis[to[i]]=1;
                dfs(to[i],deep+1);
            }
    }
    bool xyl(int x)
    {
        int i;
        for(i=fir[x];i;i=nxt[i])
            if(!vy[to[i]])
            {
                vy[to[i]]=1;
                if(!linky[to[i]]||xyl(linky[to[i]]))
                {
                    linky[to[i]]=x;return 1;
                }
            }
        return 0;
    }
    int main()
    {
        int i,j,x,y;
        while(scanf("%d",&n)==1)
        {
            ans=cnt=g=0;
            memset(fir,0,sizeof fir);memset(to,0,sizeof to);memset(nxt,0,sizeof nxt);
            memset(vis,0,sizeof vis);memset(linky,0,sizeof linky);
            for(i=1;i<=n;i++)
            {
                x=getint()+1;j=getint();
                while(j--)y=getint()+1,newnote(x,y),newnote(y,x);
            }
            vis[1]=1;dfs(1,1);
            for(i=1;i<=g;i++)
            {
                memset(vy,0,sizeof vy);
                ans+=xyl(X[i]);
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    STL"源码"剖析
    Excel如何进行SVN
    BootstrapTable+KnockoutJS
    WebApi 集成 Swagger
    Java Core和HeapDump
    深入分析 Java 中的中文编码问题(1)
    Java编码浅析(注意区分三个概念)(转)
    理解并解决GBK转UTF-8奇数中文乱码(转)
    Java实现敏感词过滤(转)
    Android MediaPlayer状态机
  • 原文地址:https://www.cnblogs.com/Darknesses/p/12002553.html
Copyright © 2011-2022 走看看