記新加入的邊的起點為$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#includeview code#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;
}
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為根的包含全部...