Fibonacci Tree HDU - 4786——解题报告
立志用更少的代碼做更高效的表達
Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him to do some research on Spanning Tree. So Coach Pang decides to solve the following problem:
Consider a bidirectional graph G with N vertices and M edges. All edges are painted into either white or black. Can we find a Spanning Tree with some positive Fibonacci number of white edges?
(Fibonacci number is defined as 1, 2, 3, 5, 8, … )
Input
The first line of the input contains an integer T, the number of test cases.
For each test case, the first line contains two integers N(1 <= N <= 105) and M(0 <= M <= 105).
Then M lines follow, each contains three integers u, v (1 <= u,v <= N, u<> v) and c (0 <= c <= 1), indicating an edge between u and v with a color c (1 for white and 0 for black).
Output
For each test case, output a line “Case #x: s”. x is the case number and s is either “Yes” or “No” (without quotes) representing the answer to the problem.
Sample Input
2
4 4
1 2 1
2 3 1
3 4 1
1 4 0
5 6
1 2 1
1 3 1
1 4 1
1 5 1
3 5 1
4 2 1
Sample Output
Case #1: Yes
Case #2: No
分析
題意:一個圖,有黑邊和白邊,黑邊權值0,白邊權值1, 問是否存在一棵生成樹,使其白邊個數(也就是總權值)為斐波那契數(1,2,3,5…)。
生成樹的概念: n個點,n-1條邊,沒有環路。
思路: 構造一個最大生成樹, 構造一個最小生成樹, 只要二者權值之間存在斐波那契數,則Yes, 因為權值每-1,一定是將一個黑邊換成了白邊。
代碼展示
/* 步驟: 1、定義結構體, 定義重載運算符 2、初始化并查集(init函數) 3、定義find函數 4、定義連接邊的函數(max函數) 5、定義建立樹的函數 */ #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 1e5 + 5;struct node{int u, v, w; //u、v是點,w是它本身的值 node() { }node(int uu, int vv, int ww) {u = uu; v = vv; w = ww;}bool operator<(const node other)const { //重載操作數 return w<other.w;} }edge[N*2];int n, m; int per[N]; int fib[N]; //斐波那契數列 void init() { //1、創建初始化的并查集 for(int i = 0; i < N; i++) per[i]=i; } int Find(int x) { //2、找邊的函數 return per[x] == x ? x : per[x]=Find(per[x]); }int mix(int a, int b) { //建立連接的過程 int fa = Find(a), fb = Find(b);if(fa != fb) {per[fa] = fb;return 1;} return 0; } int solve1() {init(); //先初始化int ans = 0, cnt = 0;for(int i = 0; i < m; i++) {int u = edge[i].u;int v = edge[i].v;int w = edge[i].w;if(mix(u,v)) {cnt++; ans+=w; //若建立連接成功,cnt邊數增加, 權值增加 }if(cnt == n-1) break; //如果邊數=n-1,則結束遍歷 } if(cnt == n-1) return ans; //如果建樹成功,則返回權值else return 0; //否則返回0 }int solve2() {init();int ans = 0, cnt = 0;for(int i = m-1; i >= 0; i--) {int u = edge[i].u;int v = edge[i].v;int w = edge[i].w;if(mix(u,v)) {cnt++;ans += w;}if(cnt == n-1) break;}if(cnt == n-1) return ans;return 0; }void in() { //構造斐波那契數列, 打表 memset(fib, 0, sizeof(fib));int a = 1, b = 1; fib[1] = 1;for(int i = 2; i <= 30; i++) {int c = a+b;if(c>=N) break;a = b; b = c; fib[c] = 1;} }int main() {int T, cas=0;scanf("%d", &T);in(); while(T--) {scanf("%d%d", &n, &m);for(int i = 0; i < m; i++) {int u, v, w;scanf("%d%d%d", &u, &v, &w);edge[i] = node(u, v, w);}//按權值排序, 正向遍歷則最小生成樹,反向遍歷則最大生成樹 sort(edge, edge+m); int mint = solve1();int maxt = solve2();int flag = 0; for(int i = mint; i <= maxt; i++) if(fib[i]) { flag = 1; break; }printf("Case #%d: ", ++cas);if(flag) printf("Yes\n");else printf("No\n");} return 0; }每日一句
懦弱囚禁人的靈魂,希望可以令你感受自由, 強者自救,圣者渡人。——《肖申克的救贖》
總結
以上是生活随笔為你收集整理的Fibonacci Tree HDU - 4786——解题报告的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hard Disk Drive HDU
- 下一篇: 测试点错的来:1024 科学计数法 (2