1463. Happiness to People!
Time limit: 1.0 second Memory limit: 64 MB
Every Santa Claus wants to surprise children with his presents. This year Santa Claus Petrovich wants to surprise children of remote Cuckooland. He is sure that in order to make a real impression he should choose a route without repeating towns. In order to bring as much happiness as possible, he plans to visit the most populated places. Petrovich took a map of Cuckooland and connected with lines some pairs of towns where, he's sure, people will wait for him. He decided not to fly between towns that are not connected. It turned out that if Petrovich can fly (using one or several flights) from town i to town j, then there is exactly one way to do this. Petrovich can start his trip in any of the towns.
Petrovich knows that when he arrives in town i, the population feels happiness Ai. And when Petrovich flies from town i to town j, he bestows happiness Cij. The same amount of happiness is bestowed if he flies from j to i. Help Santa Claus Petrovich to maximize the amount of happiness that he can bring to people.
Input
The first line contains the number N (1 ≤ N ≤ 50000) of towns in Cuckooland and the number K of pairs of towns that are connected. The second line contains numbersAi (i = 1..N); Ai ≤ 10000. Each of the following K lines contains three numbers a, b, c, which mean that when Petrovich flies from town a to town b he brings happiness c (a ≠ b; c ≤ 10000). All numbers in the input are whole and nonnegative.
Output
The first line of the output must contain the maximal amount of happiness felt by the people of Cuckooland. The second line must contain the length L of the optimal route of Santa Claus Petrovich. The third line must contain the optimal route (L numbers separated with a space). If there are several answers, you may output any of them.
Samples
input | output |
---|---|
2 1 1 1 1 2 1 |
3 2 1 2 |
8 7 1 5 4 6 10 1 2 2 1 2 1 2 3 10 2 4 1 4 5 1 4 6 2 6 7 2 6 8 3 |
37 4 5 4 2 3 |
Problem Author: Alexander Toropov, special thanks to Alexander Ipatov Problem Source: Ural SU Contest. Petrozavodsk Winter Session, January 2006
***************************************************************************************
树状dp和图论思想有许多相似之处,都要深搜找路径 经典不过这个树状dp有许多中间需要处理的地方和以前看的树状dp感觉要难,还是自己学艺不精,参考了讲解和代码;
***************************************************************************************
1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 #include<cstdio> 5 #include<cmath> 6 #include<vector> 7 #include<queue> 8 #include<stack> 9 using namespace std; 10 typedef long long LL; 11 typedef pair<LL,LL> pLL; 12 bool vis[50011]; 13 vector<pLL>a[50011]; 14 queue<int>q; 15 stack<int>stk; 16 int dp[50011][2],p[50011][2]; 17 int n,m,i,j,k; 18 int val[50011]; 19 int suma,ans; 20 int root; 21 void input() 22 { 23 cin>>n>>m; 24 suma=1; 25 for(i=1;i<=n;i++) 26 cin>>val[i]; 27 for(i=0;i<m;i++)//存邻点 28 { 29 pLL temp; 30 int st,en,w; 31 cin>>st>>en>>w; 32 temp.first=st,temp.second=w,a[en].push_back(temp); 33 temp.first=en,temp.second=w,a[st].push_back(temp); 34 } 35 36 } 37 void dfs(int x)//深搜求最大值 38 { 39 dp[x][0]=dp[x][1]=0;//0和1分别代表以x为根的左右 40 p[x][0]=p[x][1]=-1; 41 int size=a[x].size(); 42 vis[x]=true; 43 for(int i=0;i<size;i++) 44 { 45 int ds=a[x][i].first; 46 int w=a[x][i].second; 47 if(!vis[ds]) 48 { 49 dfs(ds); 50 if(dp[ds][1]+w>=dp[x][1]) 51 { 52 dp[x][0]=dp[x][1]; 53 p[x][0]=p[x][1]; 54 dp[x][1]=dp[ds][1]+w; 55 p[x][1]=ds; 56 } 57 else if(dp[ds][1]+w>dp[x][0]) 58 { 59 dp[x][0]=dp[ds][1]+w; 60 p[x][0]=ds; 61 } 62 63 64 65 } 66 } 67 dp[x][1]+=val[x]; 68 dp[x][0]+=val[x]; 69 if(dp[x][1]+dp[x][0]-val[x]>ans)//多加了个根 70 { 71 ans=dp[x][1]+dp[x][0]-val[x]; 72 root=x; 73 } 74 } 75 int findpath1(int rt)//找路径 76 { 77 int lv; 78 int suma=1; 79 while(!stk.empty())stk.pop(); 80 stk.push(rt); 81 for(lv=p[rt][1];lv!=-1;lv=p[lv][1]) 82 { 83 stk.push(lv); 84 suma++; 85 } 86 return suma; 87 } 88 int findpath2(int rt) 89 { 90 int lv; 91 int suma=0; 92 while(!q.empty())q.pop(); 93 for(lv=p[rt][0];lv!=-1;lv=p[lv][1]) 94 { 95 q.push(lv); 96 suma++; 97 } 98 return suma; 99 } 100 void solve() 101 { 102 memset(vis,false,sizeof(vis)); 103 memset(p,-1,sizeof(p)); 104 memset(dp,0,sizeof(dp)); 105 ans=-1; 106 for(int is=1;is<=n;is++) 107 if(!vis[is]) 108 dfs(is); 109 cout<<ans<<endl; 110 int a0=findpath1(root); 111 int b0=findpath2(root); 112 cout<<a0+b0<<endl; 113 while(!stk.empty())//根据栈和队列的特性 114 { 115 cout<<stk.top()<<' '; 116 stk.pop(); 117 } 118 while(!q.empty()) 119 { 120 cout<<q.front()<<' '; 121 q.pop(); 122 } 123 cout<<endl; 124 125 } 126 int main() 127 { 128 input(); 129 solve(); 130 return 0; 131 }