树形DP
樹形DP小結(jié):
1:n個(gè)點(diǎn),n-1條邊;
2:無環(huán),根結(jié)點(diǎn)可由子結(jié)點(diǎn)推出;
3:一般的狀態(tài)都是以某一個(gè)結(jié)點(diǎn)為根的子樹代表什么,
然后通過遞歸,由一個(gè)一個(gè)子結(jié)點(diǎn)推出根結(jié)點(diǎn)狀態(tài);
遞推關(guān)系:Dp[i][j]=max(dp[i][j],dp[i][k]+dp[son[i][j-k]);
說明遞推的含義,首先dp[i][j]的第一個(gè)值肯定從dp[son[i]][k]來,當(dāng)換另一個(gè)son2[i],dp[i][j]就是由倆個(gè)son推出,其他son同理;
4:對于一棵樹,可以隨意選一個(gè)點(diǎn)為根,開一個(gè)vis[]數(shù)組,記錄該結(jié)點(diǎn)是否訪問過;
http://acm.hdu.edu.cn/showproblem.php?pid=1520
最裸的樹形DP, 定義dp[i][0]表示以i為根的子樹不選i能邀請到的最大值;
Dp[i][1]表示以i為根的子樹選i能邀請到的最大值;
狀態(tài)轉(zhuǎn)移:dp[i][0]+=max(dp[son][0],dp[son][1]); dp[i][1]+=dp[son][0];
注意每個(gè)點(diǎn)的值有正有負(fù);
View Code
1 #include<cstdio>
2 #include<cstring>
3 #include<iostream>
4 #include<algorithm>
5 #include<cstdlib>
6 #include<cmath>
7 #include<vector>
8 using namespace std;
9 const int MAXN=6010;
10 int dp[MAXN][2];
11 const int INF=1000000;
12 vector <int > g[MAXN];
13 int c[MAXN];
14 int n;
15 int v[MAXN];
16 void TREEDP(int root)
17 {
18 int d=g[root].size();
19 if (d==0) {
20 dp[root][1]=c[root];
21 dp[root][0]=0;
22 return ;
23 }
24 for (int i=0;i<d;i++)
25 {
26 int c=g[root][i];
27 TREEDP(c);
28 }
29
30 dp[root][1]=c[root];
31 for (int i=0;i<d;i++)
32 {
33 int c=g[root][i];
34 if (dp[c][0]>0)
35 dp[root][1]+=dp[c][0];
36 }
37 dp[root][0]=-INF;
38 for (int i=0;i<d;i++)
39 {
40 int c=g[root][i];
41 int t=max(dp[c][1],dp[c][0]);
42 if (t>0 && dp[root][0]<0)
43 {
44 dp[root][0]=t;
45 } else if (t<0 && dp[root][0]<0)
46 {
47 if (dp[root][0]<t) dp[root][0]=t;
48 } else if (t>0 && dp[root][0]>=0)
49 {
50 dp[root][0]+=t;
51 }
52 }
53 }
54 int main()
55 {
56 // freopen("D:\in.txt","r",stdin);
57 while (~scanf("%d",&n))
58 {
59 for (int i=1;i<=n;i++)
60 {
61 scanf("%d",&c[i]);
62 g[i].clear();
63 }
64 int u,v;
65 bool vis[MAXN];
66 memset(vis,0,sizeof(vis));
67 while (~scanf("%d%d",&u,&v))
68 {
69 if (u==0 && v==0) break;
70 g[v].push_back(u);
71 vis[u]=1;
72 }
73 memset(dp,0,sizeof(dp));
74
75 for (int i=1;i<=n;i++)
76 {
77 if (vis[i]==0)
78 {
79 TREEDP(i);
80 cout<<max(dp[i][0],dp[i][1])<<endl;
81 break;
82 }
83 }
84
85
86 }
87
88 return 0;
89 }
http://acm.hdu.edu.cn/showproblem.php?pid=2412
和上一題基本一樣,但還要詢問方案是否唯一;加一個(gè)數(shù)組記錄當(dāng)前狀態(tài)是否唯一如果不唯一,當(dāng)根結(jié)點(diǎn)的狀態(tài)有它推出時(shí),根結(jié)點(diǎn)的狀態(tài)也就不唯一
//程序統(tǒng)一輸出的方式,不要cout和printf混用,倆著輸出性質(zhì)不一樣;
View Code
1 #include<cstdio>
2 #include<cstring>
3 #include<cstdlib>
4 #include<iostream>
5 #include<algorithm>
6 #include<map>
7 #include<vector>
8 #include<string>
9 using namespace std;
10 const int MAXN=210;
11 map<string,int > mp;
12 int sz;
13 vector <int >g[MAXN];
14 int dp[MAXN][2];
15 int dug[MAXN][2];
16 int vis[MAXN];
17 int n;
18 void init()
19 {
20 sz=0;
21 mp.clear();
22 for (int i=0;i<n;i++) g[i].clear();
23 memset(vis,0,sizeof(vis));
24 }
25 void TREEDP(int rt)
26 {
27 if (vis[rt]) return ;
28 vis[rt]=1;
29 int d=g[rt].size();
30 if (d==0)
31 {
32 dp[rt][0]=0;
33 dp[rt][1]=1;
34 dug[rt][0]=1;
35 dug[rt][1]=1;
36 return;
37 }
38 dp[rt][0]=dp[rt][1]=0;
39 dug[rt][0]=dug[rt][1]=1;
40 for (int i=0;i<d;i++)
41 {
42 int c=g[rt][i];
43 if (!vis[c])
44 {
45 TREEDP(c);
46 }
47 dp[rt][1]+=dp[c][0];
48 if (dug[c][0]==0) dug[rt][1]=0;
49 dp[rt][0]+=max(dp[c][1],dp[c][0]);
50 if (dp[c][1]>dp[c][0] && dug[c][1]==0)
51 {
52 dug[rt][0]=0;
53 } else
54 if (dp[c][1]<dp[c][0] && dug[c][0]==0)
55 {
56 dug[rt][0]=0;
57 } else if (dp[c][1]==dp[c][0]) dug[rt][0]=0;
58 }
59 dp[rt][1]+=1;
60
61
62 }
63 int mp_find(string s)
64 {
65 if (mp.find(s)==mp.end())
66 {
67 mp[s]=sz++;
68 }
69 return mp[s];
70 }
71 int main()
72 {
73 //freopen("D:\in.txt","r",stdin);
74 string s,s1,s2;
75 while (cin>>n)
76 {
77 if (n==0) break;
78 init();
79 cin>>s;
80 mp_find(s);
81 for (int i=0;i<n-1;i++)
82 {
83 cin>>s1>>s2;
84 int u=mp_find(s1);
85 int v=mp_find(s2);
86 g[v].push_back(u);
87 }
88
89 TREEDP(0);
90
91 if (dp[0][1]>dp[0][0])
92 {
93 if(dug[0][1]) cout<<dp[0][1]<<" Yes"<<endl;//printf("%d Yes\n",dp[0][1]);
94 else cout<<dp[0][1]<<" No"<<endl;//printf("%d No\n",dp[0][1]);
95 } else if (dp[0][1]<dp[0][0])
96 {
97 if(dug[0][0])cout<<dp[0][0]<<" Yes"<<endl;// printf("%d Yes\n",dp[0][0]);
98 else cout<<dp[0][0]<<" No"<<endl;//printf("%d No\n",dp[0][0]);
99 } else
100 {
101 cout<<dp[0][1]<<" No"<<endl;//printf("%d No\n",dp[0][1]);
102
103 }
104
105
106 }
107
108
109 return 0;
110 }
http://acm.hdu.edu.cn/showproblem.php?pid=3899
很裸的樹形DP,先一遍dfs,統(tǒng)計(jì)出以每個(gè)結(jié)點(diǎn)為根的子樹包含的隊(duì)伍,和該子樹以該子樹跟為聚集地所走的路徑,這樣就算出了以根結(jié)點(diǎn)為聚集地需要的總路程;
再一遍 dfs,由總根結(jié)點(diǎn)推到子結(jié)點(diǎn),記錄下最小值。
//對于數(shù)據(jù)大的,但有感覺沒有超,還是果斷用long long ,有可能中間計(jì)算超了;
//該題用dfs遞歸會爆棧,要手寫stack,或用C++交可以用爆棧外掛,
#pragma comment(linker, "/STACK:1024000000,1024000000")
View Code
1 #pragma comment(linker, "/STACK:1024000000,1024000000")
2 #include<cstdio>
3 #include<cstring>
4 #include<iostream>
5 #include<algorithm>
6 #include<cstdlib>
7 #include<cmath>
8 #include<vector>
9 using namespace std;
10 const int N=100100;
11 typedef __int64 ll;
12 ll dp[N];
13 ll dug[N];
14 int n;
15 ll c[N],vis[N];
16 ll ans;
17 struct node
18 {
19 int v,w;
20 };
21 vector <node> g[N];
22 void TREEDP(int rt)
23 {
24 vis[rt]=1;
25 int d=g[rt].size();
26 if (d==0)
27 {
28 dp[rt]=c[rt];
29 dug[rt]=0;
30 return;
31 }
32 dp[rt]=c[rt];
33 dug[rt]=0;
34 for (int i=0;i<d;i++)
35 {
36 int c=g[rt][i].v;
37 int w=g[rt][i].w;
38 if (vis[c]) continue;
39 TREEDP(c);
40 dp[rt]+=dp[c];
41 dug[rt]+=dp[c]*w+dug[c];
42 }
43 }
44 void init()
45 {
46 memset(dp,0,sizeof(dp));
47 for (int i=1;i<=n;i++) g[i].clear();
48 memset(vis,0,sizeof(vis));
49 memset(dug,0,sizeof(dug));
50 }
51 void solve(int rt)
52 {
53 vis[rt]=1;
54 int d=g[rt].size();
55 for (int i=0;i<d;i++)
56 {
57 int c=g[rt][i].v;
58 if (vis[c]) continue;
59 int w=g[rt][i].w;
60 ll t1=dp[c],t2=dug[c];
61 ll t3=dp[rt],t4=dug[rt];
62
63 dp[c]=t3;
64 dp[rt]=t3-t1;
65 dug[rt]=t4-t1*w-t2;
66 dug[c]=t4-w*t1+(t3-t1)*w;
67 ans=min(dug[c],ans);
68 solve(c);
69 dp[c]=t1;dug[c]=t2;
70 dp[rt]=t3;dug[rt]=t4;
71 }
72 vis[rt]=0;
73
74 }
75 int main()
76 {
77 //freopen("D:\in.txt","r",stdin);
78 while (~scanf("%d",&n))
79 {
80 for (int i=1;i<=n;i++)
81 {
82 scanf("%I64d",&c[i]);
83 }
84 init();
85 for (int i=0;i<n-1;i++)
86 {
87 int u,v,w;
88 scanf("%d%d%d",&u,&v,&w);
89 node t1={v,w};
90 g[u].push_back(t1);
91 node t2={u,w};
92 g[v].push_back(t2);
93 }
94 TREEDP(1);
95 ans=dug[1];
96 //cout<<ans<<endl;
97 memset(vis,0,sizeof(vis));
98 solve(1);
99 printf("%I64d\n",ans);
100
101 }
102
103 return 0;
104 }
http://acm.hdu.edu.cn/showproblem.php?pid=2196
求樹上離一個(gè)點(diǎn)最遠(yuǎn)的距離;我是先一遍dfs記錄下以該點(diǎn)為根的子樹的子結(jié)點(diǎn)到根的最遠(yuǎn)距離,然后轉(zhuǎn)移總根結(jié)點(diǎn),求出每個(gè)結(jié)點(diǎn)的ans;同上類似;
View Code
1
2 #include<cstdio>
3 #include<iostream>
4 #include<cstring>
5 #include<algorithm>
6 #include<cstdlib>
7 #include<cmath>
8 #include<vector>
9 using namespace std;
10 typedef long long ll;
11 const int N=10010;
12 ll dp[N];
13 struct node
14 {
15 int v,w;
16 };
17 vector<node> g[N];
18 int vis[N];
19 ll c[N];
20 int n;
21 void init()
22 {
23 for (int i=1;i<=n;i++)
24 g[i].clear();
25 memset(dp,0,sizeof(dp));
26 memset(vis,0,sizeof(vis));
27 }
28 void TREEDP(int rt)
29 {
30 vis[rt]=1;
31 int d=g[rt].size();
32 if (d==0)
33 {
34 dp[rt]=0;
35 return;
36 }
37 for (int i=0;i<d;i++)
38 {
39 ll v=g[rt][i].v;
40 ll w=g[rt][i].w;
41 if (vis[v]) continue;
42 TREEDP(v);
43 dp[rt]=max(dp[rt],dp[v]+w);
44 }
45
46 }
47 ll find(int rt,int x)
48 {
49 ll t=0;
50 int d=g[rt].size();
51 for (int i=0;i<d;i++)
52 {
53 int v=g[rt][i].v;
54 int w=g[rt][i].w;
55 if(x==v) continue;
56 t=max(t,dp[v]+w);
57 }
58 return t;
59 }
60 void solve(int rt)
61 {
62 vis[rt]=1;
63 int d=g[rt].size();
64 if (d==0)
65 {
66 c[rt]=dp[rt];
67 return;
68 }
69 for (int i=0;i<d;i++)
70 {
71 int v=g[rt][i].v;
72 if (vis[v]) continue;
73 ll w=g[rt][i].w;
74 ll t=dp[v],t3=dp[rt];
75 ll t2=find(rt,v)+w;
76
77
78 dp[v]=max(dp[v],t2);
79 dp[rt]=t2-w;
80 c[v]=dp[v];
81 solve(v);
82 dp[rt]=t3;dp[v]=t;
83
84 }
85
86 }
87 int main()
88 {
89 //freopen("D:\in.txt","r",stdin);
90 while (~scanf("%d",&n))
91 {
92 init();
93 for (int i=2;i<=n;i++)
94 {
95 int v,w;
96 scanf("%d%d",&v,&w);
97 node t1={v,w};
98 g[i].push_back(t1);
99 node t2={i,w};
100 g[v].push_back(t2);
101 }
102
103 TREEDP(1);
104 c[1]=dp[1];
105 memset(vis,0,sizeof(vis));
106 solve(1);
107 for (int i=1;i<=n;i++)
108 printf("%d\n",c[i]);
109
110 }
111 return 0;
112 }
http://acm.hdu.edu.cn/showproblem.php?pid=3586
二分+樹形DP;
據(jù)說凡是求最大最小值或最小最大值都可以二分確定一個(gè)因素,然后驗(yàn)證;
二分上限,樹形DP求不超上界切斷聯(lián)絡(luò)的最小代價(jià);
View Code
1 #include<cstdio>
2 #include<cstring>
3 #include<cstdlib>
4 #include<iostream>
5 #include<algorithm>
6 #include<cmath>
7 #include<vector>
8 using namespace std;
9 const int N=1010;
10 int dp[N];
11 int n,all;
12 int vis[N];
13 bool bo[N];
14 struct node
15 {
16 int v,w;
17 };
18 vector<node> g[N];
19
20 const int INF=1000000000;
21 void TREEDP(int rt,int c,int m)
22 {
23 vis[rt]=1;
24 int d=g[rt].size();
25
26 int t=0;
27 int flag=0;
28 for (int i=0;i<d;i++)
29 {
30 int v=g[rt][i].v;
31 int w=g[rt][i].w;
32 if (vis[v]) continue;
33 TREEDP(v,w,m);
34 if (bo[v])
35 {
36 bo[rt]=1;
37 break;
38 }
39 t+=dp[v];
40 flag=1;
41 }
42 if (bo[rt]==1)
43 {
44 if (c<=m)
45 {
46 bo[rt]=0;
47 dp[rt]=c;
48 }
49 } else
50 {
51 if (c<=m)
52 {
53 if (flag)
54 dp[rt]=min(t,c);
55 else dp[rt]=c;
56 }else
57 {
58 if (flag)
59 dp[rt]=t;
60 else bo[rt]=1;
61
62 }
63 }
64
65 }
66 bool solve(int m)
67 {
68 memset(dp,0,sizeof(dp));
69 memset(vis,0,sizeof(vis));
70 memset(bo,0,sizeof(bo));
71 TREEDP(1,INF,m);
72 if (bo[1]==1) return 0;
73 if(dp[1]<=all) return 1;
74 return 0;
75 }
76 void init()
77 {
78 for (int i=1;i<=n;i++)
79 g[i].clear();
80 }
81 int main()
82 {
83 //freopen("D:\in.txt","r",stdin);
84 while (~scanf("%d%d",&n,&all))
85 {
86 if (n==0 && all==0) break;
87 init();
88 int l=0,r=1000;
89 for (int i=2;i<=n;i++)
90 {
91 int u,v,w;
92 scanf("%d%d%d",&u,&v,&w);
93 // r=max(r,w);
94
95 node t1={v,w};
96 g[u].push_back(t1);
97 node t2={u,w};
98 g[v].push_back(t2);
99 }
100 int ans=-1;
101 while (r>l)
102 {
103 int m=(l+r)/2;
104 if (solve(m))
105 {
106 ans=m;
107 r=m;
108 }else l=m+1;
109 }
110 printf("%d\n",ans);
111
112
113 }
114 return 0;
115 }
http://acm.hdu.edu.cn/showproblem.php?pid=1561
dp[i][j]表示以i為根,攻下j個(gè)城市的最大獲得;
dp[i][j]=max(dp[i][j[,dp[son][k]+dp[i][j-k]);類似于在樹上做分組背包;
View Code
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 #include<iostream>
5 #include<cstdlib>
6 #include<cmath>
7 #include<vector>
8 using namespace std;
9 const int MAXN=210;
10 int n,m;
11 vector<int > g[MAXN];
12 int dp[MAXN][MAXN];
13 //dp[i][j] ,表示以i為根,攻下j個(gè)城市的最大獲得;
14 int c[MAXN];
15 void init()
16 {
17 memset(dp,0,sizeof(dp));
18 for (int i=0;i<=n;i++)
19 {
20 g[i].clear();
21 }
22
23 }
24 void TREEDP(int rt,int m)
25 {
26
27 int d=g[rt].size();
28 dp[rt][1]=c[rt];
29 for (int i=0;i<d;i++)
30 {
31
32 int c=g[rt][i];
33 if (m>1)
34 TREEDP(c,m-1);
35 for (int j=m;j>0;j--)
36 {
37 int v=j+1;
38 for (int k=1;k<v;k++)
39 if (dp[rt][v]<dp[rt][v-k]+dp[c][k])
40 {
41 dp[rt][v]=dp[rt][v-k]+dp[c][k];
42 }
43
44 }
45 }
46
47 }
48 int main()
49 {
50 // freopen("D:\in.txt","r",stdin);
51 while (~scanf("%d%d",&n,&m))
52 {
53 if (n==0 && m==0) break;
54 c[0]=0; init();
55 for (int i=1;i<=n;i++)
56 {
57 int v;
58 scanf("%d%d",&v,&c[i]);
59 g[v].push_back(i);
60 }
61 TREEDP(0,m+1);
62 printf("%d\n",dp[0][m+1]);
63
64 }
65 return 0;
66 }
http://acm.hdu.edu.cn/showproblem.php?pid=1011
同上;注意特判;
View Code
1 #include<cstdio>
2 #include<cstring>
3 #include<cstdlib>
4 #include<algorithm>
5 #include<iostream>
6 #include<cmath>
7 #include<vector>
8 using namespace std;
9
10 const int MAXN=110;
11 int n,m;
12 vector<int > g[MAXN];
13 int c[MAXN],w[MAXN];
14 int dp[MAXN][MAXN];
15 int vis[MAXN];
16 //dp[i][j] 以i為根花費(fèi)j能獲得的最大利益;
17
18 void TREEDP(int rt)
19 {
20
21 vis[rt]=1;
22 int d=g[rt].size();
23 for (int i=c[rt];i<=m;i++) dp[rt][i]=w[rt];
24 for (int i=0;i<d;i++)
25 {
26 int son=g[rt][i];
27 if (vis[son]==0)
28 {
29 TREEDP(son);
30
31 for (int j=m;j>=c[rt];j--)
32 {
33
34 for (int k=1;j+k<=m;k++)
35 {
36 if (dp[son][k])
37 dp[rt][j+k]=max(dp[rt][j+k],dp[rt][j]+dp[son][k]);
38
39 }
40 }
41 }
42
43 }
44 }
45 void init()
46 {
47 memset(dp,0,sizeof(dp));
48 for (int i=0;i<=n;i++) g[i].clear();
49 memset(vis,0,sizeof(vis));
50 }
51 int main()
52 {
53 //freopen("D:\in.txt","r",stdin);
54 while (~scanf("%d%d",&n,&m))
55 {
56 if (n==-1 && m==-1) break;
57 init();
58 for (int i=1;i<=n;i++)
59 {
60 int a,b;
61 scanf("%d%d",&a,&b);
62 c[i]=(a+19)/20;
63 // if (a%20) c[i]+=1;
64 w[i]=b;
65 }
66 for (int i=0;i<n-1;i++)
67 {
68 int u,v;
69 scanf("%d%d",&u,&v);
70 g[u].push_back(v);
71 g[v].push_back(u);
72 }
73 if (m==0)
74 {
75 printf("0\n");
76 continue;
77 }
78 TREEDP(1);
79 printf("%d\n",dp[1][m]);
80
81 }
82 return 0;
83 }
http://acm.hdu.edu.cn/showproblem.php?pid=4003
題意差不多,但要特別處理0的情況;
View Code
1 #include<cstdio>
2 #include<cstring>
3 #include<cstdlib>
4 #include<algorithm>
5 #include<iostream>
6 #include<vector>
7 #include<cmath>
8 using namespace std;
9 const int N=10010;
10 int dp[N][11];
11 int n,s,num;
12 int vis[N];
13 struct node
14 {
15 int v,w;
16 };
17 vector<node > g[N];
18 const int INF=1000000000;
19
20
21 void TREEDP(int rt)
22 {
23 vis[rt]=1;
24 int d=g[rt].size();
25 for (int i=0;i<d;i++)
26 {
27 int v=g[rt][i].v;
28 int w=g[rt][i].w;
29 if (vis[v]) continue;
30 TREEDP(v);
31 for (int j=num;j>=0;j--)
32 {
33 int t=INF;
34 for (int k=0;k<=j;k++)
35 {
36
37 if (j-k==0)
38 t=min(t,dp[rt][k]+dp[v][j-k]+w*2);
39 else t=min(t,dp[rt][k]+dp[v][j-k]+w*(j-k));
40
41 }
42 dp[rt][j]=t;
43 }
44 }
45
46 }
47 void init()
48 {
49 memset(dp,0,sizeof(dp));
50 memset(vis,0,sizeof(vis));
51 for (int i=0;i<=n;i++) g[i].clear();
52
53 }
54 int main()
55 {
56 //freopen("D:\in.txt","r",stdin);
57 while (~scanf("%d%d%d",&n,&s,&num))
58 {
59 init();
60 for (int i=0;i<n-1;i++)
61 {
62 int u,v,w;
63 scanf("%d%d%d",&u,&v,&w);
64 node t1={v,w};
65 g[u].push_back(t1);
66 node t2={u,w};
67 g[v].push_back(t2);
68
69 }
70 // init_dp(s);
71 memset(vis,0,sizeof(vis));
72 TREEDP(s);
73 printf("%d\n",dp[s][num]);
74 }
75 return 0;
76 }
http://acm.hdu.edu.cn/showproblem.php?pid=2242
這題主要還是縮點(diǎn);樹形DP,就隨便搞一下;
View Code
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;
const int M=20005;
const int N=10005;
const int INF=1000000000;
struct node
{
int u,v;
int next;
}edge[M*2],edge1[M*2];
int head[N],tol,cnt,dfn[N],low[N],vis[N],belong[N];
int toll,head1[N],val[N],val1[N];
int n,m,SUM,Min,scc;
stack<int > S;
void insert(int a,int b)
{
node v={a,b,head[a]};
edge[tol]=v;
head[a]=tol++;
}
void insert1(int a,int b)
{
node v={a,b,head1[a]};
edge1[toll]=v;
head1[a]=toll++;
}
void tarjan(int u,int father)
{
int j,v,flag;
dfn[u]=low[u]=cnt++;
vis[u]=1;
S.push(u);
flag=0;
for (j=head[u];j!=-1;j=edge[j].next)
{
v=edge[j].v;
if (v==father && !flag)
{
flag=1;continue;
}
if (!vis[v]) tarjan(v,u);
low[u]=min(low[u],low[v]);
}
if (dfn[u]==low[u])
{
scc++;
do
{
v=S.top();S.pop();
belong[v]=scc;
val[scc]+=val1[v];
} while (v!=u) ;
}
}
int dfs(int u,int father)
{
int j,v,sum;
sum=val[u];
for (j=head1[u];j!=-1;j=edge1[j].next)
{
v=edge1[j].v;
if (v==father) continue;
sum+=dfs(v,u);
}
Min=min(Min,abs(SUM-2*sum)) ;
return sum;
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
memset(head,-1,sizeof(head));
tol=cnt=0;
SUM=0;
for (int i=0;i<n;i++)
{
scanf("%d",&val1[i]);
SUM+=val1[i];
}
for (int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
insert(u,v);
insert(v,u);
}
memset(vis,0,sizeof(vis));
memset(val,0,sizeof(val));
scc=0;
while (!S.empty())S.pop();
tarjan(0,0);
if (scc==1)
{
printf("impossible\n");
continue;
}
toll=0;
memset(head1,-1,sizeof(head1));
for (int i=0;i<tol;i++)
{
int a=edge[i].u;
int b=edge[i].v;
if (belong[a]!=belong[b])
insert1(belong[a],belong [b]);
}
Min=INF;
dfs(1,0);
printf("%d\n",Min);
}
return 0;
}
總結(jié)
- 上一篇: 关于Fiori应用sandbox Jav
- 下一篇: 十年前,《模拟城市》是如何轰然倒塌的