贪婪与动态编程

时间:2015-10-01 14:39:00

标签: c++ algorithm greedy

Xaero住在一个叫Hackland的国家。 Hackland有一棵树的结构,N个城市通过N-1双向道路连接。每个城市的指数在[1,N]之间,没有两个城市具有相同的指数。

哈克兰总统认为在城市内旅行是安全的。然而,由于Hackland的光线条件不佳,在城市A之间,不同城市B之间旅行并不安全。

为了确保从一个城市到另一个城市的人们的安全,Hackland总裁决定在该国安装一些灯。每个城市最多可安装1盏灯。有些城市甚至可能已经安装了灯。根据总统的说法,如果在该路径上至少有一个城市安装了灯具,那么从一个城市A到另一个城市B旅行被认为是安全的。

Xaero知道Hackland预算非常有限。因此,他想通过告诉他最少的灯数来帮助他的总统,这样每个城市到其他城市的旅行都变得安全了。

输入格式

第一行输入包含一个整数T,表示测试用例的数量。每个测试用例的第一行包含一个整数N,表示该国家名为Hackland的城市数量。每个测试用例的下一行包含N个空格分隔的整数,表示国家的初始配置,即' 0' 0在第i个位置表示没有灯安装在第i个城市,而a' 1'在第i个位置表示已经在第i个城市安装了一盏灯。每个测试用例的下一行N-1行包含一对整数U和V,表示城市U和城市V之间存在双向道路。

MY Approach ::

对于这个问题,我使用的方法是,我总是用max deg选择节点。将其变亮(即使其度为0,并将其相邻节点的度数减1),我将继续执行此过程,直到任何节点的度数大于零。对于已经减轻节点,我正在使他们的deg 0并将其相邻节点的deg减小1.但我的ans对于某些测试用例不正确?任何人都可以建议我的方法有什么问题吗?

我在这里分享代码......

#include<bits/stdc++.h>
using namespace std;

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */  

    int T, i, j, max, max_index, index, count, strt, end , N ;        
    bool flag ;

    cin>> T ;        
    while(T--)            
        {            
           cin >> N ;            
           count = 0 ;            
           vector<vector<int>> tree ;            
           vector<int> init(N+1) ;            
           vector<int> deg(N+1) ;            
           fill(deg.begin(),deg.end(),0) ;            
           tree.resize(N+1) ;            
           for(i=1; i<=N; i++)
               cin >> init[i] ;

           for(i=0 ; i < N-1 ; i++)                   
               {                   
               cin>>strt>>end ;                   
               tree[strt].push_back(end) ;                   
               tree[end].push_back(strt) ;                   
               deg[strt] = deg[strt] + 1 ;                   
               deg[end] = deg[end] + 1 ;
              }

           for(i=1; i <=N ; i++)                   
               {                   
                 if(init[i]==1)                         
                     {                         
                         deg[i] = 0 ;                         
                         for(j=0 ; j < tree[i].size(); j++)                                 
                             {                                 
                                index = tree[i][j] ;                                 
                                 deg[index] = deg[index] -1 ;                                 
                             }
                     }                   
             }                                    

       while(1){               
       flag = false ;  //               
       for(i=1 ; i<= N ; i++)               
           {                
              if(deg[i] > 0){
                  flag = true ;                     
                  break ;
              }
         }               
        if(flag==false)
            break ;

        max = deg[1] ;  //            
        max_index =  1;  //            
        for(i=2; i <= N ;i++)
            {                
             if(deg[i] > max)
                {                     
                 max = deg[i] ;                     
                 max_index = i ;
                }                
           }               
        //   cout<<"max_index "<<max_index <<endl ;               
           count = count + 1 ;   // 

          deg[max_index] = 0 ;

          for(j=0; j < tree[max_index].size() ; j++)                  
              {                  
                 index = tree[max_index][j] ;                  
                 deg[index] = deg[index]- 1 ; //                  
              }            
        }

      cout<<count<<endl ;  
    }

    return 0;
}

1 个答案:

答案 0 :(得分:1)

你的方法很贪婪,而真正的解决方案是基于DP(正如你的标题所暗示的那样)。有很多例子你可能会出错,但这里有一个我认为 - 当多个节点具有相同的学位并明智地选择时你应该特别小心:

1
5
00000
1 2
1 3
2 4
3 5

请注意,即使你为这个测试用例输出正确的答案,也可能是因为纯粹的运气 - 这里你有三个2级节点,最好的解决方案是只减轻其中的两个--2和3。取决于您给予相同节点的顺序可能会最终点亮节点1,这是错误的。请注意 - 在许多其他情况下,您的解决方案会出错,这只是我认为最简单的方法。