HDU 4786 图论之最短路

来源:互联网 发布:php html实体编码转换 编辑:程序博客网 时间:2024/06/05 00:28

点击打开链接

题意:问有没有一个生成树的权值之和是斐波那契中的值

思路:分别求一次最大生成树权值和为max1和最小生成树权值和min1,如果不能生成一个树,直接输出No,不然判断min1到max1中有没有斐波那契数就行了,至于为什么可以,我感觉我队友说的比较有道理,最小生成树可以加一条边然后删一条边生成次小生成树,依次类推,我们可以用次小生成树在生成一个次小次小生成树,一直可以推到最大生成树,所以中间的值都可以,判断就行了

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;const int maxn=100010;int f[maxn],fib[30];void initinit(){    fib[1]=1;fib[2]=2;    for(int i=3;i<=30;i++) fib[i]=fib[i-1]+fib[i-2];}void init(){    for(int i=0;i<maxn;i++) f[i]=i;}int find1(int x){    if(x!=f[x]) f[x]=find1(f[x]);    return f[x];}void unite(int a,int b){    int aa=find1(a);    int bb=find1(b);    f[aa]=bb;}struct edge{    int u,v,cost;    edge(){}    edge(int a,int b,int c){u=a;v=b;cost=c;}};bool cmp1(const edge &a,const edge &b){    return a.cost<b.cost;}bool cmp2(const edge &a,const edge &b){    return a.cost>b.cost;}edge es[maxn];int V,E;int kruskal(int x){    if(x==1) sort(es,es+E,cmp1);    else sort(es,es+E,cmp2);    init();    int ans=0,sum=0;    for(int i=0;i<E;i++){        edge e=es[i];        if(find1(e.u)!=find1(e.v)){            unite(e.u,e.v);            sum++;ans+=e.cost;        }    }    if(sum==V-1) return ans;    else return -1;}int main(){    int T,t=1;    initinit();    scanf("%d",&T);    while(T--){        scanf("%d%d",&V,&E);        for(int i=0;i<E;i++) scanf("%d%d%d",&es[i].u,&es[i].v,&es[i].cost);        printf("Case #%d: ",t++);        int min1=kruskal(1);        if(min1==-1){            printf("No\n");continue;        }        int max1=kruskal(0);        int flag=0;        for(int i=1;i<=30;i++){            if(fib[i]>=min1&&fib[i]<=max1){                flag=1;break;            }        }        if(flag) printf("Yes\n");        else printf("No\n");    }    return 0;}

0 0
原创粉丝点击