zoukankan      html  css  js  c++  java
  • 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;
  • 相关阅读:
    FZU 2150 Fire Game
    POJ 3414 Pots
    POJ 3087 Shuffle'm Up
    POJ 3126 Prime Path
    POJ 1426 Find The Multiple
    POJ 3278 Catch That Cow
    字符数组
    HDU 1238 Substing
    欧几里德和扩展欧几里德详解 以及例题CodeForces 7C
    Codeforces 591B Rebranding
  • 原文地址:https://www.cnblogs.com/ibilllee/p/7651968.html
Copyright © 2011-2022 走看看