1. 程式人生 > >poj1737 Connected Graph(n點無向連通圖)

poj1737 Connected Graph(n點無向連通圖)

題目連結

題目描述:
給出n個點,求n個點的無向連通圖

分析:
巨坑啊

經典題目,有兩種方法:

總方案數-不合法方案

n個點的完全圖有C(n,2)=n(n1)2條邊,顯然就有2C(n,2)種子圖(列舉每條邊是否選擇)

f[i]表示每個點都和點1相連的連通圖的個數
假設1號點所在的連通塊大小為i
那麼和1連通的這i1個點就有C(n1,i1)種選擇,方案數為C(n1,i1)f[i]

其它ni個點間任意連邊即可,方案數為2C

(ni,2)

則有遞推公式:

f[n]=2C(n,2)i=1n1f[i]C(n1,i1)2C(ni,2)

在程式碼實現上,基本上都是高精度
所以網上的程式碼都是什麼Java,python之類的

直接求方案數

考慮去掉1號點時,2號點的情況
設此時2所在的連通塊共有i個點
i個點和剩下的ni個點分別處在兩個不同連通塊中(下面就要把這兩個連通塊連線在一起)
其方案數為f[i],f[ni],2號點需要在剩下的點(除去點1,點2)中選擇

i1個點同處一個連通塊,方案數為C(n2,i1)
而這i個點與除去1的ni1個點(這ni1個點都與點1連通)都需要通過1號點來連線
所以與2號點連通的i個點與1號點至少有1條邊連線,方案數為2i1
故這樣的情況總共有:f[i]f[ni]C(n2,i1)(2i1)

則有遞推公式

f[n]=i=1n1f[i]f[ni]C(n2,i1)(2i1)

這種思路xue微有點困難,而且還是需要用高精度
不過只需要高精加和高精乘即可(比第一種方法簡單一點)

tip

方法二code

#include<cstdio>
#include<iostream>
#include<cstring>
#define ll long long

using namespace std;

int n,nn=2;
struct node{
    int o[400],len;

    node operator *(const node &a) const {
        int L=(len+a.len);
        node ans; ans.clear();
        ans.len=L;
        for (int i=1;i<=len;i++)
            for (int j=1;j<=a.len;j++) {
                ans.o[i+j-1]+=o[i]*a.o[j];
                ans.o[i+j]+=ans.o[i+j-1]/10;
                ans.o[i+j-1]%=10;
            }
        while (!ans.o[ans.len]) ans.len--;
        return ans;
    }

    node operator +(const node &a) const {
        int L=max(len,a.len);
        int d=0;
        node ans; ans.clear();
        for (int i=1;i<=L;i++) {
            ans.o[i]=o[i]+a.o[i]+d;
            d=ans.o[i]/10;
            ans.o[i]%=10;
        }
        ans.len=L;
        if (d) ans.o[++ans.len]=d;
        return ans;    
    }

    void clear() {memset(o,0,sizeof(o));len=0;}

    node get(ll x) {
        node ans; ans.clear();
        while (x) {
            ans.o[++ans.len]=x%10;
            x/=10;
        }
        return ans;
    }
};
node f[51],c[51][51];

void prepare() {
    c[0][0].len=1; c[0][0].o[1]=1;
    for (int i=1;i<=50;i++) {
        c[i][0].o[1]=1; c[i][0].len=1;
        for (int j=1;j<=i;j++) 
            c[i][j]=c[i-1][j]+c[i-1][j-1]; 
    }
}

void solve(int n) {
    node t; 
    for (int i=1;i<n;i++) {
        t=t.get((1LL<<i)-1); 
        f[n]=f[n]+f[i]*f[n-i]*c[n-2][i-1]*t;
    }
}

void print(int n) {
    for (int i=f[n].len;i>=1;i--)
        printf("%d",f[n].o[i]);
    printf("\n");
}

int main()
{
    f[1].o[1]=1; f[1].len=1;
    f[2].o[1]=1; f[2].len=1;
    nn=2;
    prepare();
    while (scanf("%d",&n)!=EOF&&n) {
        if (n<=nn) {print(n);continue;}
        for (int i=nn+1;i<=n;i++) 
            solve(i);
        nn=n;
        print(n);
    }
    return 0;
}

相關推薦

poj1737 Connected Graphn連通

題目連結 題目描述: 給出n個點,求n個點的無向連通圖 分析: 巨坑啊 經典題目,有兩種方法: 總方案數-不合法方案 nn個點的完全圖有C(n,2)=n(n−1)2C(n,2)=n(n

【XSY1295】calc nn條邊連通計數 prufer序列

ring pre end ctime 節點 splay 按順序 sin algorithm 題目大意   求\(n\)個點\(n\)條邊的無向連通圖的個數   \(n\leq 5000\) 題解   顯然是一個環上有很多外向樹。   首先有一個東西:\(n\)個點選\(k\

連通的割

1. 割點與連通度 在無向連通圖中,刪除一個頂點v及其相連的邊後,原圖從一個連通分量變成了兩個或多個連通分量,則稱頂點v為割點,同時也稱關節點(Articulation Point)。一個沒有關節點的連通圖稱為重連通圖(biconnected graph)。若在連通圖上

論】求連通的割

1. 割點與連通度 在無向連通圖中,刪除一個頂點v及其相連的邊後,原圖從一個連通分量變成了兩個或多個連通分量,則稱頂點v為割點,同時也稱關節點(Articulation Point)。一個沒有關節點的連通圖稱為重連通圖(biconnected graph)。若在連通圖上至少刪去k 個頂點才能破壞圖的連通性,則

連通的最小割詳解以及java原始碼實現

import java.util.*; /**尋找割點*/ public class FindArt { static class Node { Node(String name) { this.name=name; Childen=new Arra

用Tarjan演算法求連通&&割邊

/** 割點割邊挺好理解的,割點就是一個無向連通圖,把其中一個點 挖掉剩下的圖不連通,割邊就是把一條邊砍掉不連通 比如:有一個通訊網路,要求一顆炸彈,把這個通訊網路搞得不連通,問 炸哪個點或哪條邊。 Tarjan 演算法實現求割邊

poj1523 SPF 連通 求割 關節點 tarjan演算法

SPF Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5103 Accepted: 2347 Description Consider the two networks shown below.

leetcode 847. Shortest Path Visiting All Nodes 連通遍歷最短路徑

sel shu turn 判斷 lam 最短 額外 動態 訪問 設計最短路徑 用bfs 天然帶最短路徑 每一個狀態是 當前的階段 和已經訪問過的節點 下面是正確但是超時的代碼 class Solution: def shortestPathLength(self,

LeetCode 547. 朋友圈數量--連通

解析 方法一:DFS 遍歷所有人,對於每一個人,尋找他的好友,找到好友後再找這個好友的好友,這樣深度優先遍歷下去,設定一個visited記錄是否已經遍歷了這個人。 因為如果m個人最多m個朋友圈,設定後visited後,相同的朋友圈會檢測到visited[i]!=0就會不算數

[帶標號連通計數 容斥原理 多項式求逆 多項式求ln 模板題] BZOJ 3456 城市規劃

可以通過容斥求出答案的表示式fi=2C2i−∑j=1i−1Cj−1i−1∗fj∗2C2i−j 其中前一部分表示i個點任意連邊 後半部分列舉1所在的連通塊然後容斥掉 ∑j=1ifj(j−1)!∗2C2i−j(i−j)!=2C2i(i−1)! 這是個卷積的

連通中兩點間所有路徑的演算法

http://bbs.csdn.net/topics/360001583 之前在csdn就這個問題發帖求教過,過了幾天沒看到回覆就沒再關心。後來自己設計了一個演算法,在公司的專案中實踐了一下,效果還可以,貼出來供大家參考。演算法要求:1. 在一個無向連通圖中求出兩個給

連通的最小生成樹(c語言版)

完整原始碼地址:[email protected]:hglspace/MinCostSpTree.git 圖例:                     1 普里姆演算法 /*  普里姆演算法:假設N={v,{E}}是連通圖,TE是N上的最小生成樹中邊的集合

資料結構 之 連通

下列關於無向連通圖特性的敘述中,正確的是 Ⅰ.所有頂點的度之和為偶數Ⅱ.邊數大於頂點個數Ⅲ.至少有一個頂點的度為1 如下圖所示為一個無向連通圖:任何兩個節點之前都是連通的,都存在一條路徑,並且圖中沒有方向。        (1)頂點的度為頂點所連線的邊的個數,無向連通圖中的

tarjan板子割邊連通分量

low函式實際上可以不開成陣列的(話是這麼說,但是會佔用棧空間,所以說還是老老實實寫成靜態陣列開在外面比較好)。 割點: void tarjan_point(int i,int fd)//給邊上標號

【ZSTU4213 2015年12月浙理工校賽 D】【雙連通分量tarjan演算法】One-Way Roads 連通確定邊的方向使得全任意兩點間可達

4213: One-Way Roads Time Limit:1 Sec  Memory Limit:128 MB  Special JudgeSubmit:133  Solved:45 Description In the ACM kingdom, there a

893C. Rumor#謠言傳播賦權&搜索

ble pan 要求 amp color nbsp style n) def 題目出處:http://codeforces.com/problemset/problem/893/C 題目大意:一個城中有一些關系圈,圈內會傳播謠言,求使每個人都知道謠言的最小花費 #incl

n個結點的完全的生成樹的個數

頭部閒扯 今天閒來在google搜了一下cantjie,突然發現我的部落格竟然被引用過,很是驚訝。因為雖然僅僅只是過去一年,我現在看我去年寫的部落格,就有種“這寫的什麼垃圾玩意”的感覺,沒想到竟然也會有人瀏覽並引用我的部落格。 想來這個部落格閒置一年多了,突

相關演算法無權的廣度優先遍歷BFS-非遞迴版本

核心 採用鄰接表作為圖資料的儲存結構 對訪問過的節點進行記錄,文中採用HashSet實現 採用佇列存放未訪問的子節點,不斷更新佇列 BFS採用佇列實現很簡單,採用遞迴反而更復雜了 本文建立的圖結構如

POJ 1386 Play on Words歐拉通路 連通

tput mouse char s tdi 任務 input using 否則 表示 題意 見下方中文翻譯 每一個單詞能夠看成首尾兩個字母相連的一條邊 然後就是輸入m條邊 推斷是否能構成有向歐拉通路了 有向圖存在歐拉通路的充要條件: 1. 有向圖的基圖連通;

洛谷P3371單源最短路徑Dijkstra版鏈式前星處理

jks 沒有 style bool while add 是什麽 最短 短路徑 首先講解一下鏈式前向星是什麽。簡單的來說就是用一個數組(用結構體來表示多個量)來存一張圖,每一條邊的出結點的編號都指向這條邊同一出結點的另一個編號(怎麽這麽的繞) 如下面的程序就是存鏈式前向星。(