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
题意:
给出许多黑色或白色的无向边构成一个图,问是否有一颗生成树使得白色边的数量为斐波那契数列中的值。
思路:
很容易想到,先通过按颜色进行贪心分别求出生成树的最少min和最多max需要的白边数目,那么一定可以通过增删边得到[min,max]数量的白边的生成树。
这个是我看到题目就马上想到的想法,但证明的话也只能比较模棱两可的理论证明,没法具体给出有说服力的证明。只能说,当优先选取黑色边的时候,min是必须取的构造生成树的白边数目,因此之后的生成树都可以看作由这颗生成树增删边构成。
坑点就是给出的图不一定是连通图,还需要额外判断……WA了好几次。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <iterator>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;
#define pi acos(-1)
#define s_1(x) scanf("%d",&x)
#define s_2(x,y) scanf("%d%d",&x,&y)
#define s_3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define s_4(x,y,z,X) scanf("%d%d%d%d",&x,&y,&z,&X)
#define s_5(x,y,z,X,Y) scanf("%d%d%d%d%d",&x,&y,&z,&X,&Y)
#define S_1(x) scan_d(x)
#define S_2(x,y) scan_d(x), scan_d(y)
#define S_3(x,y,z) scan_d(x), scan_d(y), scan_d(z)
#define PI acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define fOR(n,x,i) for(int i=n;i>=x;i--)
#define fOr(n,x,i) for(int i=n;i>x;i--)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
#define ll long long
#define mp make_pair
#define pb push_back
#define mian main
#define ture true
typedef long long LL;
typedef pair <int, int> ii;
const int INF = 0x3f3f3f3f;
const LL LINF = 0x3f3f3f3f3f3f3f3fLL;
const int dx[] = {-1, 0, 1, 0, 1, -1, -1, 1, 0};
const int dy[] = {0, 1, 0, -1, -1, 1, -1, 1, 0};
const int maxn = 1e5 + 10;
const int maxx = 1e5 + 10;
const double EPS = 1e-9;
const double eps = 1e-9;
const int mod = 1e9 + 7;
template <class T> inline T min(T a, T b, T c) {return min(min(a, b), c);}
template <class T> inline T max(T a, T b, T c) {return max(max(a, b), c);}
template <class T> inline T min(T a, T b, T c, T d) {return min(min(a, b), min(c, d));}
template <class T> inline T max(T a, T b, T c, T d) {return max(max(a, b), max(c, d));}
template <class T> inline bool scan_d(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
inline bool scan_lf(double &num) {
char in;
double Dec = 0.1;
bool IsN = false, IsD = false;
in = getchar();
if (in == EOF) return false;
while (in != '-' && in != '.' && (in < '0' || in > '9')) in=getchar();
if (in == '-') {IsN = true; num = 0;}
else if (in == '.') {IsD = true; num = 0;}
else num = in - '0';
if (!IsD) {
while (in = getchar(), in >= '0' && in <= '9') {num *= 10; num += in - '0';}
}
if (in != '.') {
if (IsN) num = -num;
return true;
}
else{
while (in = getchar(), in >= '0' && in <= '9') {
num += Dec * (in - '0');
Dec *= 0.1;
}
}
if (IsN) num = num;
return true;
}
void Out(LL a) {if(a < 0) {putchar('-'); a = -a;}if(a >= 10) Out(a / 10); putchar(a % 10 + '0');}
void print(LL a) {Out(a), puts("");}
/**********************************************WHITE_YASHA**********************************************/
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
//cerr << "run time is " << clock() << endl;
struct edge {
int u, v, w;
edge() {}
edge(int _u, int _v, int _w) {
u = _u;
v = _v;
w = _w;
}
};
bool cmp_white(edge a, edge b) {return a.w > b.w;}
bool cmp_black(edge a, edge b) {return a.w < b.w;}
vector <edge> edges;
vector <int> fib;
int fa[maxn];
int t, n, m;
void fibonacci() {
fib.pb(1); fib.pb(2);
W (fib[fib.size() - 1] + fib[fib.size() - 2] <= maxx) {
fib.pb(fib[fib.size() - 1] + fib[fib.size() - 2]);
}
}
void init_fa() {
FOR (1, n, i) fa[i] = i;
}
int find_fa(int x) {return fa[x] == x ? fa[x] : fa[x] = find_fa(fa[x]);}
void mix_fa(int x, int y) {
int fx = find_fa(x), fy = find_fa(y);
if (fx != fy) fa[fy] = fx;
}
int kruskal() {
int ans = 0;
init_fa();
FOr (0, edges.size(), i) {
if (find_fa(edges[i].u) != find_fa(edges[i].v)) {
mix_fa(edges[i].u, edges[i].v);
if (edges[i].w) ans++;
}
}
return ans;
}
bool check() {
init_fa();
FOr (0, edges.size(), i) mix_fa(edges[i].u, edges[i].v);
FOR (1, n, i) if (find_fa(i) != find_fa(1)) return false;
return true;
}
int main() {
fibonacci();
s_1(t);
FOR (1, t, cas) {
edges.clear();
init_fa();
s_2(n, m);
W (m--) {
int u, v, w;
s_3(u, v, w);
edges.pb({u, v, w});
}
printf("Case #%d: ", cas);
if (!check()) {
puts("No");
continue;
}
sort(edges.begin(), edges.end(), cmp_black);
int minn = kruskal();
sort(edges.begin(), edges.end(), cmp_white);
int maxx = kruskal();
puts(*lower_bound(fib.begin(), fib.end(), minn) <= maxx ? "Yes" : "No");
}
}