Fibonacci Tree
Time Limit : 4000/2000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Problem Description
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
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, ... )
(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
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
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
区域赛都是有思维难度的题吧,果然还是不够熟悉图,完全没有思路。
看了别人的题解也才知道:
如果一棵生成树最少含有low条白边,最多含有hig条白边,那么含有x(low<=x&&x<=hig)条白边的生成树一定存在
不知道为什么中间的每一个生成树都存在(望大神告知),但我自己画了几个图还没找出反例
#include <cstdio>
#include <algorithm>
using namespace std;
struct Edge {
int s,e,c;
Edge(int ss=0,int ee=0,int cc=0):s(ss),e(ee),c(cc) {}
bool operator < (const Edge& a) const {
return c<a.c;
}
}g[100005];
int par[100005],pa,pb,f[25];
int getPar(int a) {
if(par[a]!=a)
par[a]=getPar(par[a]);
return par[a];
}
void Merge(int a,int b) {
pa=getPar(a),pb=getPar(b);
if(pa!=pb)
par[pb]=pa;
}
int main() {
int n,m,i,T,kase=0,cnt,low,hig;
bool flag;
i=1,f[0]=1,f[1]=2;
while(f[i]<100005) {
f[i+1]=f[i]+f[i-1];
++i;
}
scanf("%d",&T);
while(kase<T) {
scanf("%d%d",&n,&m);
low=hig=0,cnt=1;
for(i=0;i<m;++i)
scanf("%d%d%d",&g[i].s,&g[i].e,&g[i].c);
for(i=1;i<=n;++i)
par[i]=i;
sort(g,g+m);
for(i=0;i<m&&cnt!=n;++i) {
if(getPar(g[i].s)!=getPar(g[i].e)) {
Merge(g[i].s,g[i].e);
++cnt;
low+=g[i].c;
}
}
flag=false;
if(cnt==n) {//如果图是连通的
cnt=1;
for(i=1;i<=n;++i)
par[i]=i;
for(i=m-1;i>=0&&cnt!=n;--i) {
if(getPar(g[i].s)!=getPar(g[i].e)) {
Merge(g[i].s,g[i].e);
++cnt;
hig+=g[i].c;
}
}
i=0;
while(f[i]<low)
++i;
if(f[i]<=hig)
flag=true;
}
printf("Case #%d: %s\n",++kase,flag?"Yes":"No");
}
return 0;
}