Interconnect - POJ 3156 期望+状压dp

Interconnect
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 1107 Accepted: 380 Special Judge

Description

There are two serious problems in the Kingdom of Lipshire: the roads and the fools who build them. Once upon a time, the King of Lipshire has decided to improve the road system because some roads became completely impassable — it was easier to travel cross-country instead of using those roads.

By King’s decree, new roads are to be built in Lipshire. Of course, the new road system must interconnect all towns, i. e. there must be a path connecting any two towns of Lipshire.

The road administration of Lipshire has resources to build exactly one road per year. Unfortunately, the fools who build these roads are completely out of control. So, regardless of the orders given, the fools randomly select two different towns a and b and build a road between them, even when those towns are already connected by a road. All possible choices are equiprobable. The road is build in such a manner that the only points where a traveler can leave it are the towns connected by this road. The only good thing is that all roads are bidirectional.

The King knows about the problem, but he cannot do anything about it. The only thing King needs to know is the expected number of years to wait before the road system of Lipshire becomes interconnected. He asked you to provide this information.

Input

The first line of the input contains two integers n and m (2 ≤ n ≤ 30, 0 ≤ m ≤ 1 000) — the number of towns in Lipshire, and the number of roads which are still good. The following m lines describe roads, one per line. Each road is described with two endpoints — two integer numbers ui and vi (1 ≤ uivi ≤ nui ≠ vi). There can be multiple roads between two towns, but the road from a town to itself is not allowed.

Output

Output the expected number of years to wait for the interconnected road system. If the system is already interconnected, output zero as an answer. Output the number with at least six precise digits after the decimal point.

Sample Input

sample input #1
2 1
1 2

sample input #2
4 2
1 2
3 4

Sample Output

sample output #1
0.0

sample output #2
1.5

题意:给你一些点和边,每次随机让其中两个点相连,问你使得所有的点连通,增加的边的期望是多少。

思路:num[i]表示恰好有i个点连通的区域有多少个,S状压这种情况,S2表示让其中某些区域相连后的状压情况dp[S]=(k1*dp[S2_1]+k2*dp[S2_2]...+k3*dp[S])/[n*(n-1)/2]+1.这是基本的转移方程,n*(n-1)/2为一共有多少种连接方式,k表示达到S2的有几种连接方式。

           另外我的代码在vj上交了之后跑出了141ms,目前直接上了第一的位置,【虽然拿自己的号只跑出了157ms

AC代码如下:

#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
typedef unsigned long long ll;
struct node
{
    int num[35];
    double p;
}box[10010];
map<ll,int> match;
int n,n2,m,p[40],sum[40],num;
ll Hash[40],MOD=1e9+7;
int find(int x)
{
    return p[x]==x ? p[x] : p[x]=find(p[x]);
}
void Union(int u,int v)
{
    u=find(u);
    v=find(v);
    if(u!=v)
    {
        p[u]=v;
        sum[v]+=sum[u];
    }
}
void debug(int pos)
{
    for(int i=1;i<=5;i++)
       printf("%d ",box[pos].num[i]);
    printf("\n");
}
double solve(ll S)
{
    int pos=match[S],i,j,k,temp=0;
    ll S2;
    double ret=0;
    if(box[pos].num[0]==1)
      return box[pos].p;
    box[pos].num[0]=1;
    if(S==Hash[n])
    {
        box[pos].p=0;
        return 0;
    }
    for(i=1;i<=n;i++)
    if(box[pos].num[i]>0)
      for(j=i+1;j<=n;j++)
         if(box[pos].num[j]>0)
          {
              S2=S-Hash[i]-Hash[j]+Hash[i+j];
              if(match[S2]==0)
              {
                  num++;
                  match[S2]=num;
                  for(k=1;k<=n;k++)
                     box[num].num[k]=box[pos].num[k];
                  box[num].num[i]--;
                  box[num].num[j]--;
                  box[num].num[i+j]++;
              }
              k=box[pos].num[i]*i*box[pos].num[j]*j;
              ret+=k*solve(S2);
              temp+=k;
          }
    for(i=1;i<=n;i++)
       if(box[pos].num[i]>=2)
       {
           S2=S-2*Hash[i]+Hash[i*2];
           if(match[S2]==0)
           {
               num++;
               match[S2]=num;
               for(k=1;k<=n;k++)
                  box[num].num[k]=box[pos].num[k];
               box[num].num[i]-=2;
               box[num].num[i*2]++;
           }
           j=box[pos].num[i]*i;
           k=j*(j-1)/2-i*(i-1)/2*box[pos].num[i];
           ret+=k*solve(S2);
           temp+=k;
       }
    box[pos].p=(ret+n2)/temp;
    return box[pos].p;
}
int main()
{
    int i,j,k,u,v;
    ll S;
    Hash[0]=1;
    for(i=1;i<=30;i++)
       Hash[i]=Hash[i-1]*MOD;
    scanf("%d%d",&n,&m);
    n2=n*(n-1)/2;
    for(i=1;i<=n;i++)
    {
        p[i]=i;
        sum[i]=1;
    }
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&u,&v);
        Union(u,v);
    }
    for(i=1;i<=n;i++)
       if(p[i]==i)
         box[1].num[sum[i]]++;
    S=0;
    for(i=1;i<=n;i++)
       S+=(ll)box[1].num[i]*Hash[i];
    match[S]=1;num=1;
    printf("%.6f\n",solve(S));
}




Vector CANape x64是一款由Vector Informatik GmbH公司开发的专业CAN总线分析软件,用于汽车及各种工业领域的数据采集、诊断以及系统测试。这款工具主要用于处理和分析车载网络的数据流,支持多种通信协议,包括CAN (Controller Area Network)、LIN (Local Interconnect Network)、FlexRay等。 关于您提到的“Error + Unable to start measurement!”,这通常意味着在尝试开始测量过程时遇到了某些错误。可能的原因有很多,以下是一些常见的原因及其解决办法: ### 错误原因及解决方案 1. **硬件连接问题**:检查所有连接到CANape的硬件设备是否已正确连接并供电。确保所有的电缆都插接良好,特别是CAN和LIN总线的电缆。 2. **驱动程序问题**:确认您的计算机上安装了最新的CANape驱动程序,并且它们与硬件兼容。有时,过时或损坏的驱动可能会导致无法正常运行测量任务。 3. **软件版本问题**:确保您使用的CANape版本是最新的。旧版本可能存在已知的 bug 或安全漏洞,这些问题在新版本中已被修复。 4. **许可问题**:如果没有有效的软件许可,可能会遇到启动测量的问题。检查您的许可证状态,确保所有必要的许可证都在有效期内并且已经激活。 5. **配置错误**:检查您的测量配置设置是否正确。有时候错误的配置会阻止测量的启动,比如错误的通道设置、错误的数据记录选项或者是未选择正确的硬件设备。 6. **系统资源不足**:如果计算机内存或处理器性能不足以支持运行CANape和正在进行的测量操作,也可能引发此错误。确保有足够的系统资源可用。 7. **日志文件信息**:最后一步是在“Write窗口”查看详细的错误信息。通常这个窗口会提供更多的细节,帮助确定问题的具体来源。错误描述可能会指出具体的故障点,如特定的设备ID、错误代码或其他关键信息。 --- 针对上述情况,建议首先从最基本的步骤开始排查问题,例如重启电脑和CANape软件,检查硬件连线,更新驱动和软件版本等。如果问题依然存在,详细查看“Write窗口”的错误日志将会非常有帮助,可能需要结合提供的错误信息进一步深入调试。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值