zoukankan      html  css  js  c++  java
  • 最小生成树计数——JSOI2008

    略有难度的最小生成树问题:
    先排序算出某一长度的边有几条,放到tong[],再用krus求某一长度的边需要几条,xu[],再用枚举的方法举例出某一长度的符合条件为几条(再枚举下一种边时。把边覆盖上),分别为f1,f2,f3……再把f1,f2,f3相乘……(当然乘的过程不要忘了mod31011)
    ps:比较郁闷的是数组开小了,一直wa,稍微开大点TLE,再开大,AC……我就奇怪为什么别人的程序数组开小没问题,囧……
    其实还有一种矩阵的解法,速度更快……自己看看论文吧
    View Code
    #include<stdio.h>
    #include
    <iostream>
    #include
    <algorithm>
    using namespace std;

    int n,m,f[19909];
    int tempf[19909];
    int tong[10999];//保存相同边的个数
    int xu[19909];//保存需要相同边几条
    struct data
    {
    int fr;
    int to;
    int w;
    }edge[
    109909];

    bool cmp(data a,data b)
    {
    return a.w<b.w;
    }

    int find(int pos)
    {
    if(f[pos]==-1)
    return pos;
    return f[pos]=find(f[pos]);
    }

    int un(int a,int b)
    {
    int fa=find(a),fb=find(b);
    if(fa==fb) return 0;
    f[fa]
    =fb;return 1;
    }

    void krus()
    {
    int i,j,k;
    for(i=1;i<=n;i++)
    {
    f[i]
    =-1;
    }
    for(i=1;i<=m;i++)
    {
    xu[i]
    =0;tong[i]=0;
    }
    sort(
    &edge[1],&edge[1+m],cmp);
    int kind=1,chang=edge[1].w;//需要不同边种

    int tre=0;
    for(i=1;i<=m;i++)
    {
    if(edge[i].w==chang)//同种长度的边需要几条
    {
    tong[kind]
    ++;
    }
    else
    {
    kind
    ++;
    chang
    =edge[i].w;
    tong[kind]
    ++;
    }

    if(un(edge[i].fr,edge[i].to)==1)
    {
    xu[kind]
    ++;
    tre
    ++;
    }
    }

    if(tre!=(n-1))
    {
    printf(
    "0\n");return ;
    }

    int bian=0,kbian=0,cc,all;
    for(i=1;i<=n;i++)
    {
    f[i]
    =-1;
    tempf[i]
    =-1;
    }
    all
    =1;
    int shu[20],sadd;
    for(i=1;i<=kind;i++)//一共有kind种长度
    {
    cc
    =0;
    for(j=1;j<=(1<<tong[i]);j++)
    {
    sadd
    =1;
    for(k=0;k<tong[i];k++)
    {
    if(j&(1<<k))
    {
    sadd
    ++;
    }
    }
    if(sadd-1!=xu[i])continue;

    sadd
    =1;
    for(k=0;k<tong[i];k++)
    {
    if(j&(1<<k))
    {
    shu[sadd]
    =k+1;
    sadd
    ++;
    }
    }
    for(k=1;k<=n;k++)
    {
    tempf[k]
    =f[k];
    }
    //保存临时点
    int add=0;//是否等于xu[i]
    for(k=1;k<=xu[i];k++)
    {
    if(un(edge[kbian+shu[k]].fr,edge[kbian+shu[k]].to)==1)
    {
    add
    ++;
    }
    }

    for(k=1;k<=n;k++)
    {
    f[k]
    =tempf[k];
    }
    if(add==xu[i])
    cc
    ++;

    }
    for(j=1;j<=tong[i];j++)//更新f[]
    {
    un(edge[j
    +kbian].fr,edge[j+kbian].to);
    }

    kbian
    +=tong[i];
    all
    =all*cc%31011;
    }

    printf(
    "%d\n",all);
    }

    int main()
    {
    int i;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    for(i=1;i<=m;i++)
    {
    scanf(
    "%d%d%d",&edge[i].fr,&edge[i].to,&edge[i].w);
    }
    krus();
    }

    return 0;
    }
  • 相关阅读:
    通过jQuery修改ui的顺序
    iOS用模型取代字典的好处
    iOS开发NSBundle、UIImageView和UIButton总结
    php数组中关于某个元素进行排序
    VMware 11安装Mac OS X 10.10
    js中的in_array
    localStorage中js数组的存储和读取
    google地图通过js计算当前位置与其余多个点之间的最近距离
    通过js修改图片的css样式,实现简单的图片旋转
    Javac不是内部或外部指令
  • 原文地址:https://www.cnblogs.com/huhuuu/p/1960118.html
Copyright © 2011-2022 走看看