组合数学:
一篇讲逆元的很不错的博客:http://blog.youkuaiyun.com/acdreamers/article/details/8220787
求很大组合数(逆元加快速幂)
typedef long long LL;
const int MOD = 1e9+7;
const int MAXN = 1e6+10;
LL inv[MAXN];
void inverse(){
inv[1]=1;
for(int i=2;i<MAXN;i++){
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
}
}
LL Cm[MAXN],Ck[MAXN];
LL _pow(LL a,int n){
if(n==0) return 1;
LL sum=_pow(a,n/2);
sum=sum*sum%MOD;
if(n&1) sum=sum*a%MOD;
return sum;
}
int n,m,k;
void get_C(){
Ck[0]=Cm[0]=1;
for(int i=1;i<=k;i++){
Cm[i]=Cm[i-1]%MOD*(m-i+1)%MOD*inv[i]%MOD;
Ck[i]=Ck[i-1]%MOD*(k-i+1)%MOD*inv[i]%MOD;
}
}
图论:
单源最短路径spfa两种写法(dfs和bfs)
int spfa_bfs(int s)
{
queue <int> q;
memset(d,0x3f,sizeof(d));
d[s]=0;
memset(c,0,sizeof(c));
memset(vis,0,sizeof(vis));
q.push(s); vis[s]=1; c[s]=1;
//顶点入队vis要做标记,另外要统计顶点的入队次数
int OK=1;
while(!q.empty())
{
int x;
x=q.front(); q.pop(); vis[x]=0;
//队头元素出队,并且消除标记
for(int k=f[x]; k!=0; k=nnext[k]) //遍历顶点x的邻接表
{
int y=v[k];
if( d[x]+w[k] < d[y])
{
d[y]=d[x]+w[k]; //松弛
if(!vis[y]) //顶点y不在队内
{
vis[y]=1; //标记
c[y]++; //统计次数
q.push(y); //入队
if(c[y]>NN) //超过入队次数上限,说明有负环
return OK=0;
}
}
}
}
return OK;
}
int spfa_dfs(int u)
{
vis[u]=1;
for(int k=f[u]; k!=0; k=e[k].next)
{
int v=e[k].v,w=e[k].w;
if( d[u]+w < d[v] )
{
d[v]=d[u]+w;
if(!vis[v])
{
if(spfa_dfs(v))
return 1;
}
else
return 1;
}
}
vis[u]=0;
return 0;
}
网络流
求最大流的Edmonds-Karp算法(bfs实现)
const int maxn = 50 + 5;
const int INF = 0x7f7f7f7f;
struct Edge{
int from,to,cap,flow;
Edge(int u=0,int v=0 ,int c=0,int f=0): from(u),to(v),cap(c),flow(f){}
};
struct EdmondsKarp{
int n,m;
vector<Edge> edges;
vector<int> G[maxn];
int a[maxn];
int p[maxn];
void Init(int n){
for(int i=0;i<n;i++) G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int cap){
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
int MaxFlow(int s,int t){
int flow=0;
for(;;){
memset(a,0,sizeof(a));
queue<int> Q;
Q.push(s);
a[s]=INF;
while(!Q.empty()){
int x=Q.front(); Q.pop();
for(int i=0;i<G[x].size();i++){
Edge& e=edges[G[x][i]];
if(!a[e.to]&&e.cap>e.flow){
a[e.to]=min(a[x],e.cap-e.flow);
p[e.to]=G[x][i];
Q.push(e.to);
}
}
if(a[t]) break;
}
if(!a[t]) break;
for(int u=t;u!=s;u=edges[ p[u] ].from){
edges[ p[u] ].flow+=a[t];
edges[ p[u]^1 ].flow -= a[t];
}
flow += a[t];
}
return flow;
}
};
EdmondsKarp g;
const int maxn = 50 + 5;
const int INF = 0x7f7f7f7f;
struct Edge{
int from,to,cap,flow;
Edge(int u=0,int v=0 ,int c=0,int f=0): from(u),to(v),cap(c),flow(f){}
};
struct EdmondsKarp{
int n,m;
vector<Edge> edges;
vector<int> G[maxn];
int a[maxn];
int p[maxn];
void Init(int n){
for(int i=0;i<n;i++) G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int cap){
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
int MaxFlow(int s,int t){
int flow=0;
for(;;){
memset(a,0,sizeof(a));
queue<int> Q;
Q.push(s);
a[s]=INF;
while(!Q.empty()){
int x=Q.front(); Q.pop();
for(int i=0;i<G[x].size();i++){
Edge& e=edges[G[x][i]];
if(!a[e.to]&&e.cap>e.flow){
a[e.to]=min(a[x],e.cap-e.flow);
p[e.to]=G[x][i];
Q.push(e.to);
}
}
if(a[t]) break;
}
if(!a[t]) break;
for(int u=t;u!=s;u=edges[ p[u] ].from){
edges[ p[u] ].flow+=a[t];
edges[ p[u]^1 ].flow -= a[t];
}
flow += a[t];
}
return flow;
}
};
EdmondsKarp g;