Alice just bought a very big house with N rooms and N-1 doors,which each door connects two rooms. Besides,each room have at least one door and at most 3 doors(of course Alice can go to every room in this house).
However, a modern person cannot live without WIFI, so Alice wants to put M wireless routers in several rooms. As the routers are cheap, only adjacent rooms(which have a door connect to this room) can receive it, and each router works independently.
Since M routers may cannot cover every room, Alice tells you the satisfaction point S[i] she could have if room i have WIFI.
Please Help Alice to calculate the maximum satisfaction point she can get to in total.
The first line is two integers N(2<=2<=1000), M(1<=M<=N,M<=100) Then are N numbers, each shows the satisfaction S[i] (1<=S[i]<=10) point of room i. Then are N-1 lines, each contains two integer x,y, which represents a door is between room x and y.
Just output the maximum point of satisfaction
Time limit per test:The faster then better
5 1
1 2 3 4 5
2 1
3 2
4 2
5 3
10
首先明确一点,这是一个图的问题。这个房子抽象成一个图,图的每个顶点代表房间,顶点数N是房间数。 N-1 门就是图的边数。这是一个稀疏图,所以应该用邻接表去存。 M个路由器去覆盖房间以求最大的满意度,这是一个DP问题,显然求解两个路由器覆盖房间的最大满意度是包括了求解一个路由器覆盖方法的最大满意度。
抽象: S[i]= S[i-1]+x; // 就是说M个路由器的满意度肯定是建立在求出M-1个路由器的满意度的基础上。
最后就是可能不需要M个路由器就把所有房间都覆盖到了,此时就没有必要继续求解了。
package worksApplication;
import java.util.*;
public class Main{
VNode[] adjlist;
private int n;
private int e;
public static int MAXVERTEX=1010;
public static int INFINITY=99999;
public static int MINDATA=(-99999);
private boolean[] visited;
protected class ANode{
int adjV;
ANode nextArc;
int weight;
}
protected class VNode{
int Vertex;//
ANode firstArc;
}
public Main(int n,int e){
this.n=n;
this.e=e;
//path=new int[n+1];//
//dist=new int[n+1];//distance or sum of weight between s and destination
adjlist=new VNode[n];
for(int i=0;i<n;i++)//from 1 to n,not 0!
adjlist[i]=new VNode();
}
public boolean createGraph(Scanner s){
// Scanner s=new Scanner(System.in);
visited=new boolean[MAXVERTEX];
ANode edge,edgex;
for(int i=0;i<n;i++){
int tmp=s.nextInt();
if(tmp>=1&&tmp<=10)
adjlist[i].Vertex=tmp;//satisfation point
else{
System.out.println("error input,out of range");
return false;
}
}
for(int i=0;i<n;i++){
//dist[i]=INFINITY;//-1 not suitable for Dij
adjlist[i].firstArc=null;
}
for(int k=0;k<e;k++){
int m,d;
m=s.nextInt()-1;d=s.nextInt()-1;//weight=s.nextInt()
if(m<0||n<0)
return false;
edge=new ANode();
edge.adjV=d;
edge.nextArc=adjlist[m].firstArc;
adjlist[m].firstArc=edge;
//undirected graph
edgex=new ANode();
edgex.adjV=m;
edgex.nextArc=adjlist[d].firstArc;
adjlist[d].firstArc=edgex;
}
return true;
}
public boolean isConnected(){
for(int i=0;i<n;i++)
if(visited[i]==false)
return false;
return true;
}
public int subMaxEx(){
int max=MINDATA;
int index=-1;
for(int i=0;i<n;i++) {
ANode edge=adjlist[i].firstArc;
if(visited[i])
continue;//end i,because it already visied
int sum=adjlist[i].Vertex;
while(edge!=null){
if(!visited[edge.adjV])
{sum+=adjlist[edge.adjV].Vertex;}
edge=edge.nextArc;
}
if(sum>max&&!visited[i]){
max=sum;
index=i;
}
}
//only here we do the check
visited[index]=true;
ANode edgex=adjlist[index].firstArc;
while(edgex!=null){
visited[edgex.adjV]=true;
edgex=edgex.nextArc;
}
return max;
}
public int findMaxSatisfaction(int routers){
//initialize a table
//int[] storage=new int[n];
int maxSatisfaction=0;
int M=0;//the number that routers cover all rooms
/*for(int i=0;i<n;i++){
ANode edge=adjlist[i].firstArc;
int sum=adjlist[i].Vertex;
while(edge!=null){
sum+=adjlist[edge.adjV].Vertex;
edge=edge.nextArc;
}
storage[i]=sum;
}*/
//Begining DP
if(routers==1)
// maxSatisfaction=subMax(storage);
maxSatisfaction=subMaxEx();
else{
for(int k=0;k<routers;k++){
//visited[]
if(isConnected())
{
M=k;//the graph already cover in M rounters
break;
}
maxSatisfaction+=subMaxEx();
}
}
if(routers>=M&&M!=0){
int sumx=0;
for(int i=0;i<n;i++)
sumx+=adjlist[i].Vertex;
maxSatisfaction=sumx;
}
return maxSatisfaction;
}
public static void main(String[] args) {
// TODO: Implement your program
@SuppressWarnings("resource")
Scanner s=new Scanner(System.in);
int n=s.nextInt();
int router=s.nextInt();
int maxSatisfaction;
if(n<2||n>1000||router<=0||router>n||router>100)
{
System.out.println("Out of range!");
return;
}
int e=n-1;//n-1 lines
Main g=new Main(n,e);
if(!g.createGraph(s))
return;
// g.printPath();
maxSatisfaction=g.findMaxSatisfaction(router);
System.out.println(maxSatisfaction);
}
}