W 國的交通呈一棵樹的形狀。W 國一共有 n−1 個城市和 nnn 個鄉村,其中城市從 111 到 n−1 編號,鄉村從 111 到 nnn 編號,且 111 號城市是首都。道路都是單向的,本題中咱們只考慮從鄉村通往首都的道路網絡。對於每個城市,恰有一條公路和一條鐵路通向這座城市。對於城市 iii,通向該城市的道路(公路或鐵路)的起點,要麼是一個鄉村,要麼是一個編號比 iii 大的城市。沒有道路通向任何鄉村。除了首都之外,從任何城市或鄉村出發只有一條道路;首都沒有往 外的道路。從任何鄉村出發,沿着惟一往外的道路走,總能夠到達首都。html
W 國的國王小 W 得到了一筆資金,他決定用這筆資金來改善交通。因爲資金有限,小 W 只能翻修 n−1 條道路。小 W 決定對每一個城市翻修剛好一條通向它的道路,即從公路和鐵路中選擇一條並進行翻修。小 W 但願從鄉村通向城市能夠儘量地便利,因而根據人口調查的數據,小 W 對每一個鄉村制定了三個參數,編號爲 iii 的鄉村的三個參數是 aia_iai,bib_ibi 和 cic_ici。假設從編號爲 iii 的鄉村走到首都一共須要通過 xxx 條未翻修的公路與 yyy 條未翻修的鐵路,那麼該鄉村的不便利值爲node
ci⋅(ai+x)⋅(bi+y)c_i \cdot (ai + x) \cdot (bi + y)ci⋅(ai+x)⋅(bi+y)在給定的翻修方案下,每一個鄉村的不便利值相加的和爲該翻修方案的不便利值。ios
翻修 n−1 條道路有不少方案,其中不便利值最小的方案稱爲最優翻修方案,小 W 天然但願找到最優翻修方案,請你幫助他求出這個最優翻修方案的不便利值。網絡
第一行爲正整數 nnn。 接下來 n−1 行,每行描述一個城市。其中第 iii 行包含兩個數 si,tis_i, t_isi,ti。sis_isi 表示通向第 iii 座城市的公路的起點,tit_iti 表示通向第 iii 座城市的鐵路的起點。若是 si>0s_i > 0si>0,那麼存在一條從第 sis_isi 座城市通往第 iii 座城市的公路,不然存在一條從第 −si-s_i−si 個鄉村通往第 iii 座城市的公路;tit_iti 相似地,若是 ti>0t_i > 0ti>0,那麼存在一條從第 tit_iti 座城市通往第 iii 座城市的鐵路,不然存在一條從第 −ti-t_i−ti 個鄉村通往第 iii 座城市的鐵路。ide
接下來 nnn 行,每行描述一個鄉村。其中第 iii 行包含三個數 ai,bi,cia_i, b_i, c_iai,bi,ci,其意義如題面所示。ui
輸出一行一個整數,表示最優翻修方案的不便利值。atom
6 2 3 4 5 -1 -2 -3 -4 -5 -6 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
54
如圖所示,咱們分別用藍色、黃色節點表示城市、鄉村;用綠色、紅色箭頭分別表示公路、鐵路;用加粗箭頭表示翻修的道路。spa
一種不便利值等於 545454 的方法是:翻修通往城市 222 和城市 555 的鐵路,以及通往其餘城市的公路。用→\rightarrow→和⇒\Rightarrow⇒表示公路和鐵路,用∗→和∗⇒表示翻修的公路和鐵路,那麼:code
總的不便利值爲 9+10+9+12+8+6=549 + 10 + 9 + 12 + 8 + 6 = 549+10+9+12+8+6=54。能夠證實這是本數據的最優解。htm
9 2 -2 3 -3 4 -4 5 -5 6 -6 7 -7 8 -8 -1 -9 1 60 1 1 60 1 1 60 1 1 60 1 1 60 1 1 60 1 1 60 1 1 60 1 1 60 1
548
在這個樣例中,顯然應該翻修全部公路。
12 2 4 5 3 -7 10 11 9 -1 6 8 7 -6 -10 -9 -4 -12 -5 -2 -3 -8 -11 53 26 491 24 58 190 17 37 356 15 51 997 30 19 398 3 45 27 52 55 838 16 18 931 58 24 212 43 25 198 54 15 172 34 5 524
5744902
共 202020 組數據,編號爲 1∼20。
對於編號 ≤4\le 4≤4 的數據,n≤20n \le 20n≤20;
對於編號爲 5∼8 的數據,ai,bi,ci≤5,n≤50;
對於編號爲 9∼12 的數據,n≤2000n \le 2000n≤2000;
對於全部的數據,n≤20000n \le 20000n≤20000,1≤ai,bi≤601 \le a_i, b_i \le 601≤ai,bi≤60,1≤ci≤1091 \le c_i \le 10^91≤ci≤109,si,tis_i, t_isi,ti 是 [−n,−1]∩(i,n−1] 內的整數,任意鄉村能夠經過不超過 404040 條道路到達首都。
#include<iostream> #include<cstdio> #include<cstring> #define maxn 50 using namespace std; int map[maxn][maxn]; int n,m,head[maxn],num,a[maxn],b[maxn],c[maxn],son[maxn][2]; struct node{int to,pre,v,w;}e[maxn*maxn]; void Insert(int from,int to,int w){ e[++num].to=to; e[num].w=w; e[num].pre=head[from]; head[from]=num; } int cnt[maxn][2]; long long ans=1000000000000000; void dfs(int x,int cnt0,int cnt1){ if(x<=n){ cnt[x][0]=cnt0; cnt[x][1]=cnt1; } for(int i=head[x];i;i=e[i].pre){ int to=e[i].to; if(e[i].w==0&&e[i].v==0)dfs(to,cnt0+1,cnt1); else if(e[i].w==1&&e[i].v==0)dfs(to,cnt0,cnt1+1); else dfs(to,cnt0,cnt1); } } long long count(int sta){ for(int i=1;i<n;i++){ if(sta&(1<<(i-1))){//連向右孩子的邊被重建 e[map[i+n][son[i+n][0]]].v=0; e[map[i+n][son[i+n][1]]].v=1; } else {//連向左孩子的邊被重建 e[map[i+n][son[i+n][0]]].v=1; e[map[i+n][son[i+n][1]]].v=0; } } dfs(n+1,0,0); long long res=0; for(int i=1;i<=n;i++){ res+=1LL*c[i]*(a[i]+cnt[i][0])*(b[i]+cnt[i][1]); } return res; } int main(){ scanf("%d",&n); m=n+n-1; int x,y; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); if(x<0)x=-x; else x+=n; if(y<0)y=-y; else y+=n; son[i+n][0]=x;son[i+n][1]=y; Insert(i+n,x,0);map[i+n][x]=map[x][i+n]=num; Insert(i+n,y,1);map[i+n][y]=map[y][i+n]=num; } for(int i=1;i<=n;i++)scanf("%d%d%d",&a[i],&b[i],&c[i]); for(int i=0;i<(1<<(n-1));i++){ ans=min(ans,count(i)); } cout<<ans<<endl; return 0; }
#include<iostream> #include<cstdio> #include<cstring> #define maxn 20010 using namespace std; int n,son[maxn][2]; long long f[maxn][50][50]; struct node{long long x,y,z;}a[maxn]; long long dfs(int x,int p,int q){ if(x>=n){ int now=x-n+1; return a[now].z*(a[now].x+p)*(a[now].y+q); } if(f[x][p][q]!=f[n+1][41][41])return f[x][p][q]; return f[x][p][q]=min(dfs(son[x][0],p,q)+dfs(son[x][1],p,q+1),dfs(son[x][1],p,q)+dfs(son[x][0],p+1,q)); } int main(){ int x,y; scanf("%d",&n); memset(f,127,sizeof(f)); for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); if(x<0)x=-x+n-1; if(y<0)y=-y+n-1; son[i][0]=x; son[i][1]=y; } for(int i=1;i<=n;i++) scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].z); printf("%lld\n",dfs(1,0,0)); return 0; }