題意:平面上有n個點(1<=n<=1000),你的任務是讓所有n個點連通,為此, 你可以新建一些邊,費用等於兩個端點的歐幾里得距離的平方。另外還有q(0<=q<=8)個**(數量小,可列舉),可以購買,如果你購買了第i個**,該** 中的所有結點將變得相互連通,第i個**的花費為ci。
分析:按照劉汝佳的思路做的。首先求一次本身的最小生成樹值,然後列舉購買的**(二進位制列舉),每次購買了之後,將其權值設為0,並且加進最小生成樹。
1 #include2 #include3 #include4view code#define ll long long
5using
namespace
std;
6const
int maxn=1005;7
intx[maxn],y[maxn],p[maxn];
8#define repu(i, a, b) for(int i = (a); i < (b); i++)
9int bb[260
];10
int tran(int
h)11
19return
i;20}21
int find(int
x)22
25struct
edge
2633 } _e[maxn*maxn],e[maxn];
34int q[8][maxn],c[8],t[8
];35
intn,m,r,cnt;
36void
init()
3740
ll kruscal()
4151}52
return
ret;53}
54int
main()
5568 repu(i,1,n+1
)69 scanf("
%d%d
",&x[i],&y[i]),p[i]=i;
70 repu(i,1
,n)71 repu(j,i+1,n+1
)72 _e[++m]=(edge)73;
76 sort(_e+1,_e+m+1
);77 ll ans=0
;78 repu(i,1,m+1)79
89 }///
本身的最小生成樹
90 repu(b,0,1
<
91106
}107
}108 ansx +=kruscal();
109 ans=min(ans,ansx);
110}
111 printf("
%lld\n
",ans);
112if(t) printf("\n"
);113
}114
return0;
115 }
每次求最小生成樹的時候,都會加進去幾條權值是0的邊,一定會被選,剩下的邊也一定會從裸求的最小生成樹種找到。第一求的時候捨棄的邊可以永遠捨棄。
二進位制列舉子集
利用二進位制的 開關 特性列舉 詳細為 如果給定集合a大小為n,則想象a 的每乙個元素相應乙個開關位 0或1 0表示不出現,1表示出現。當每乙個元素的開關位的值確定時,就得到乙個子集。因此共同擁有2 n 1種情況 全0為空集,這裡不考慮 我們利用區間 1,2 n 1 該區間上的每乙個整數相應乙個子集...
技巧 二進位制法列舉子集
我們來看乙個可以用二進位制列舉的方法解決的題目 話說大詩人李白,一生好飲 幸好他從不開車 一天,他提著酒壺,從家裡出來,酒壺中有酒兩斗 他邊走邊唱 無事街上走,提壺去打酒 逢店加一倍,遇花喝一斗 這一路上,他一共遇到店 5 次,遇到花 10 次,已知最後一次遇到的是花,他正好把酒喝光了 請你計算李白...
做實驗 解題報告(二進位制列舉子集)
有一天,你實驗室的老闆給你布置的這樣乙個實驗。首先他拿出了兩個長度為 n 的數列 a 和 b,其中每個 a i 以二進位制表示乙個集 合。例如數字 5 101 2 表示集合 第 i 次實驗會準備乙個小盒子,裡面裝 著集合 a i 所有非空子集的紙條。老闆要求你從中摸出一張紙條,如果滿足你摸出的 紙條...