• Perfect Service [POJ 3398]


    Perfect Service

    描述
    网络由N个通过N-1个通信链路连接的计算机组成,使得任何两台计算机可以通过独特的路由进行通信。如果两台计算机之间存在通信链路,则称这两台计算机是相邻的。计算机的邻居是与它相邻的一组计算机。为了快速访问和检索大量信息,我们需要选择一些作为服务器的计算机向其邻居提供资源。请注意,服务器可以为其所有邻居提供服务。如果每个客户端(非服务器)由一个服务器提供服务,则网络中的一组服务器形成完美的服务。问题是找到最少数量的服务器,形成一个完美的服务,我们称这个号码完美的服务号码。
    我们假设N(≤10000)是一个正整数,这N个计算机的编号从1到N.例如,图1示出了由六个计算机组成的网络,其中黑色节点表示服务器,白色节点表示客户端。在图1(a)中,服务器3和5不形成完美的服务,因为客户端4与服务器3和5两者相邻,因此由两个服务器服务,这与服务器相违背。相反,服务器3和4形成完美的服务,如图1(b)所示。这个集合也具有最小的基数。因此,这个例子的完美服务号码等于两个。
    您的任务是编写一个程序来计算完美的服务号码。

    输入
    输入由多个测试用例组成。每个测试用例的格式如下:第一行包含一个正整数N,表示网络中的计算机数量。下一个N-1行包含所有通信链路,每条链路包含一行。每行由两个由单个空格分开的正整数表示。最后,第(N + 1)行的0表示第一个测试用例的结束。
    下一个测试用例从上一个结束符号0开始。-1表示整个输入的结束。

    输出
    输出包含每个测试用例的一行。每行包含正整数,即
    完美的服务号码。

    样例输入
    6
    1 3
    2 3
    3 4
    4 5
    4 6
    0
    2
    1 2
    -1

    样例输出
    2
    1

    显然,一个很裸的最小支配集

    使用树形DP的做法:

    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    #include <cmath>
    #define inf 9999999
    #define maxn 10005
    using namespace std;
    int n,head[maxn*2],dp[maxn][3],cnt;
    struct Edge{
        int to;int next;
    }edge[2*maxn];
    void add(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void DP(int x,int fa)
    {
        dp[x][0]=1;dp[x][2]=0;
        int sum=0,inc=inf;bool flag=false;
        for(int i=head[x];i!=-1;i=edge[i].next)
        {
            int to=edge[i].to;
            if(to==fa)  continue;
            DP(to,x);
            dp[x][0]+=min(dp[to][0],min(dp[to][1],dp[to][2]));
    
            if(dp[to][0]<=dp[to][1])
            {
                sum+=dp[to][0];
                flag=true;
            }
            else
            {
                sum+=dp[to][1];
                inc=min(inc,dp[to][0]-dp[to][1]);
            }
    
            if(dp[to][1]!=inf&&dp[x][2]!=inf) dp[x][2]+=dp[to][1];
            else dp[x][2]=inf;
        }
        if(inc==inf&&!flag)
            dp[x][1]=inf;
        else
        {
            dp[x][1]=sum;
            if(!flag)
                dp[x][1]+=inc;
        }
    }
    int main()
    {
        int a,b,t;
        while(scanf("%d",&n))
        {
            memset(head,-1,sizeof(head));
            for(int i=1;i<n;i++)
            {
                scanf("%d %d",&a,&b);
                add(a,b);add(b,a);
            }
            scanf("%d",&t);
            DP(1,0);
            printf("%d
    ",min(dp[1][0],dp[1][1]));
            if(t==-1)   break;
        }
        return 0;
    }

    使用贪心的做法:

    `#include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #define maxn 10005 
    using namespace std;
    int head[2*maxn],ans,n,cnt,point,book[maxn],fa[maxn];
    bool vis[maxn];
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch>'9'||ch<'0')   {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    struct Edge{
        int to;int next;
    }edge[2*maxn];
    inline void add(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dfs(int index)
    {
        book[++point]=index;
        int i,j;
        for(i=head[index];i!=-1;i=edge[i].next)
        {
            if(!vis[edge[i].to])
            {
                vis[edge[i].to]=true;
                fa[edge[i].to]=index;
                dfs(edge[i].to);
            }
        }
    }
    inline void mds()
    {
        int i,j;
        bool s[maxn],set[maxn];
        memset(s,0,sizeof(s));
        memset(set,0,sizeof(set));
        for(i=n;i>=1;i--)
        {
            int now=book[i];
            if(!s[i])
            {
                if(!set[fa[i]])
                {
                    set[fa[i]]=true;
                    ++ans;
                }
                s[i]=true;
                s[fa[i]]=true;
                s[fa[fa[i]]]=true;
            }
        }
    }
    int main()
    {
        int i,j,k,t;
        while(1)
        {
            n=read();
            point=0;
            ans=0;
            cnt=0;
            memset(edge,0,sizeof(edge));
            memset(book,0,sizeof(book));
            memset(fa,0,sizeof(fa));
            memset(vis,0,sizeof(vis));
            memset(head,-1,sizeof(head));
            for(i=1;i<n;i++)
            {
                k=read();t=read();
                add(k,t);
                add(t,k);
            }
            t=read();
            vis[1]=true;
            dfs(1);
            mds();
            printf("%d
    ",ans);
            if(t==-1)break;
    
        }
    
        return 0;
  • 相关阅读:
    java中一个类中没有公共的构造方法,则说明不能让外界去new对象。
    PyQt IDE 环境搭建
    移动App开发基本技术面
    创业公司的技术管理
    软件工程师职业道德规范和实践要求
    比较好的刷题网站推荐
    对于程序员在boss直聘求职的建议
    cocospod 安装和使用
    TabBarController和其他view无法建立Relationship segue的原因
    面试与反面试的一些问题
  • 原文地址:https://www.cnblogs.com/ibilllee/p/7651968.html
Copyright © 2020-2023  润新知