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
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; }