題目: http://acm.hdu.edu.cn/showproblem.php?pid=4786
題意: 存不存在所含白邊數為菲波那契數的生成樹(包含圖中所有節點)。
找出生成樹中所含白邊最多和最少的生成樹中所含白邊數, 就是按照邊的黑白排一下序, 組成一個區間[a, b]; 然後在區間[a, b]中枚舉菲波那契數。 參考bin神代碼。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
bool flag1, flag2; int sum, Y;
struct Sorrow
{
int a, b, c;
} edge[100001];
bool cmp1(Sorrow a, Sorrow b)
{
return a.c < b.c;
}
bool cmp2(Sorrow a, Sorrow b)
{
return a.c > b.c;
}
int father[100001], n;
void init()
{
//memset(father, -1, sizeof(father));
for(int i = 1; i <= n; i++)
father[i] = i;
}
int Find(int a)
{
if(father[a] == a)
return a;
else
return father[a] = Find(father[a]);
}
int mercy(int a, int b, int c)
{
// int Y = 0;
int Q = Find(a);
int P = Find(b);
if(Q != P)
{
father[Q] = P;
if(c)
Y++;
}
return Y;
}
bool Judge()
{
int cnt = 0;
for(int i = 1; i <= n; i++)
if(father[i] == i)
{
cnt++;
if(cnt > 1)
return false;
}
return true;
}
int b[100001];
int Bitch()
{
sum = 1;
b[0] = 1; b[1] = 2;
while(b[sum] < 100001)
{
b[sum+1] = b[sum] + b[sum-1];
sum++;
}
}
int main()
{
int T, Q = 1;
scanf("%d", &T);
while(T--)
{
int m, L, R;
scanf("%d %d", &n, &m); init();
for(int i = 0; i < m; i++)
scanf("%d%d%d", &edge[i].a, &edge[i].b, &edge[i].c);
sort(edge, edge+m, cmp1); Y = 0;
for(int i = 0; i < m; i++)
L = mercy(edge[i].a, edge[i].b, edge[i].c);
// flag1 = Judge();
init();
sort(edge, edge+m, cmp2); Y = 0;
for(int i = 0; i < m; i++)
R = mercy(edge[i].a, edge[i].b, edge[i].c);
flag2 = Judge();
printf("Case #%d: ", Q++);
if(flag2 == false)
{
printf("No\n");
continue;
}
Bitch();
bool flag = false;
for(int i = 0; i < sum; i++)
{
if(b[i] >= L && b[i] <= R)
flag = true;
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
轉載于:https://www.cnblogs.com/soTired/p/4827753.html