bzoj4011 HNOI2015 落憶楓音

2022-05-15 05:57:38 字數 3009 閱讀 2976

記新加入的邊的起點為$x$,終點為$y$

首先,我們先考慮新加入的邊沒有構成環的情況,即在原圖中$x$能到$y$:

這時還是乙個有向無環圖。

根據朱劉演算法的推論,記$indegree[i]$表示點$i$的入度,那麼答案就是$\sum\limits_^indegree[i]$

現在考慮新加入的邊構成了環的情況,即在原圖中$y$能到$x$:

我們發現,其實$\sum\limits_^indegree[i]$算多了非法情況。

我們統計非法情況的個數。

我們發現在非法情況中一定包含新加入的邊和一條原圖$y$到$x$的路徑組成的簡單環;對於不在這個簡單環上每個點$i$,任選一條以點$i$為終點的有向邊,有$degree[i]$個選擇。

所以非法情況的個數是:

$\sum\limits_\sum\limits_indegree[j]$

$=\sum\limits_\frac^indegree[j]}indegree[j]}$

用dp。

記$f[i]=\sum\limits_\frac^indegree[j]}indegree[j]}$

易知$f[y]=\frac^indegree[j]}$

根據拓撲序dp。

如果有一條$u$到$v$邊,那麼$f[v]+=\frac$

然後輸出$\sum\limits_^indegree[i]-f[x]$即可。

注意$y=1$的特殊情況。

這題的巧妙之處是我們發現合法情況非常難統計,但是我們我們知道合法情況和非法情況的和,並且非法情況比較容易統計,運用了補集的思想。

#include#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

//#include適用於cf,uoj,但不適用於poj

using

namespace

std;

typedef

long

long

ll;typedef

double

db;typedef pair

pii;

typedef complex

cp;#define mmst(a,v) memset(a,v,sizeof(a))

#define mmcy(a,b) memcpy(a,b,sizeof(a))

#define fill(a,l,r,v) fill(a+l,a+r+1,v)

#define re(i,a,b) for(i=(a);i<=(b);i++)

#define red(i,a,b) for(i=(a);i>=(b);i--)

#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)

#define fi first

#define se second

#define m_p(a,b) make_pair(a,b)

#define p_b(a) push_back(a)

#define sf scanf

#define pf printf

#define two(k) (1<

inline t sqr(t x)

template

inline void upmin(t &t,t tmp)

template

inline void upmax(t &t,t tmp)

inline

int sgn(db x)

const db pi=acos(-1.0

);int

gint()

for(;z!=eof && isdigit(z);res=res*10+z-'

0',z=getchar());

return (neg)?-res:res;

}ll gll()

for(;z!=eof && isdigit(z);res=res*10+z-'

0',z=getchar());

return (neg)?-res:res;

}const

int maxn=100000

;const

int maxm=200000

;const ll mod=1000000007

;int

n,m,x,y;

int now,first[maxn+100

];struct tedgeedge[maxm+100

];ll degree[maxn+100],_degree[maxn+100

];ll f[maxn+100

],ans;

void addedge(int u,int v)

ll power(ll a,ll k)return

x;}queue

q;intmain()

ans=1

; re(i,

1,n)_degree[i]=degree[i];

degree[y]++;

re(i,

2,n)ans=ans*degree[i]%mod;

if(y==1)

f[y]=ans;

re(i,

1,n)if(_degree[i]==0

)q.push(i);

while(!q.empty())}}

ans-=f[x];

ans=(ans%mod+mod)%mod;

cout

return0;

}

view code

BZOJ 4011 HNOI2015 落憶楓音

題意 給乙個有向無環圖,然後叫一條邊,問以1為根的生成樹數量。題面好長啊,出題人真能編故事 先考慮不加那條邊,則麼ans d 2 d 3 d 4 d n d為入度 因為在乙個dag中,只要除根以外的點每個點選一條入邊,就能獲得一棵生成樹。現在考慮加了這條邊,如果再這麼算,就有可能出現環的情況,所以我...

BZOJ4011 HNOI2015 落憶楓音

用脈絡樹總數減去不合法的情況 即樹上有環的情況 拓撲序dp,注意特判連的邊指向1的情況 學到了新姿勢 線性求逆元 原理 假設現在要求a的逆元,x mod a,y mod a ax y 0 ax y a 1 x y 1 ax y 0 ax y a 1 x y 1 code include includ...

BZOJ4011 HNOI2015 落憶楓音

不妨假設楓葉上有 n個穴位,穴位的編號為 1 n。有若干條有向的脈絡連線著這些穴位。穴位和脈絡組成乙個有向無環圖 稱之為脈絡圖 例如圖 1 穴位的編號使得穴位 1 沒有從其他穴位連向它的脈絡,即穴位 1 只有連出去的脈絡 由上面的故事可知,這個有向無環圖存在乙個樹形子圖,它是以穴位 1為根的包含全部...