最小生成树
Kruskal
struct edge{
int from,to,val;
}e[maxn];
bool operator < (
const edge&a,
const edge&b){
return a.val<b.val;
}
int find(
int a){
return fa[a]==a ? fa[a] : fa[a]=find(fa[a]);
}
void Kruskal(){
int cnt=
0;
sort(e+
1,e+m+
1);
for(
int i=
1,j=
0;i<=m,j<n-
1;i++){
int a=e[i].
from,b=e[i].to;
if(find(a)!=find(b)){
fa[find(a)]=find(b);
j++;
}
}
}
最小完全图
void Union(
int a,
int b){
int x=find(a),y=find(b);
f[y]+=f[x];
fa[x]=y;
}
Prim&前向星
typedef pair<
int,
int> pii;
int cnt=
0,head[maxn],dis[maxn];
bool vis[maxn];
struct edge{
int to,next,val;
}e[maxn*
3];
bool cmp(pii a,pii b){
return a.first>b.first;
}
void add(
int u,
int v,
int val){
for(
int i=head[u];~i;i=e[i].next){
if(e[i].to==v){
if(e[i].val>val) e[i].val=val;
return;
}
}
e[++cnt].to=v;
e[cnt].val=val;
e[cnt].next=head[u];
head[u]=cnt;
}
void Prim(
int s){
int ans=
0;
memset(dis,-
1,
sizeof(dis));
memset(vis,
0,
sizeof(vis));
priority_queue<pii,
vector<pii>,cmp> q;
for(
int i=head[s];~i;i=e[i].next){
dis[e[i].to]=e[i].val;
q.push(make_pair(dis[e[i].to],e[i].to))
}
dis[s]=
0; vis[s]=
1;
while(!q.empty()){
pii u=q.top(); q.pop();
if(vis[u.second])
continue;
vis[u.second]=
1;
ans+=u.first;
for(
int i=head[u.second];~i;i=e[i].next){
int j=e[i].to;
if(!vis[j]&&(dis[j]>e[i].val||dis[j]==-
1)){
dis[j]=e[i].val;
q.push(make_pair(dis[j],j));
}
}
}
printf(
"%d\n",ans);
}
最短路
SPFA
int dis[maxn];
bool vis[maxn];
bool SPFA(
int s){
int stat[maxn];
bool flag=
0;
memset(stat,
0,
sizeof(stat));
memset(dis,
0x3f,
sizeof(dis));
memset(vis,
0,
sizeof(vis));
queue<int> q;
q.push(s); vis[s]=
1;
while(!q.empty()){
if(flag)
break;
int tmp=q.front(); q.pop(); vis[tmp]=
0;
for(
int i=head[tmp];~i;i=e[i].next){
int cur=e[i].to;
if(dis[cur]>dis[tmp]+e[i].val){
dis[cur]=dis[tmp]+e[i].val;
vis[cur]=
1; stat[cur]++;
if(stat[cur]>n){
flag=
1;
break;
}
q.push(cur);
}
}
}
return flag;
}
Dijkstra
void Dijkstra(
int s){
priority_queue<pii> q;
bool cmp(pii a,pii b){
return a.first>b.first;
}
memset(dis,
0x3f,
sizeof(dis));
memset(vis,
0,
sizeof(vis));
q.push(make_pair(dis[s]=
0,s));
for(
int i=head[s];~i;i=e[i].next){
int cur=e[i].to;
dis[cur]=e[i].val;
q.push(make_pair(dis[cur],cur));
}
while(!q.empty()){
int tmp=q.top(); q.pop();
if(vis[tmp])
continue;
for(
int i=head[tmp];~i;i=e[i].next){
int cur=e[i].to;
if(!vis[cur]&&dis[cur]>dis[tmp]+e[i].val){
dis[cur]=dis[tmp]+e[i].val;
vis[cur]=
1; q.push(make_pair(dis[cur],cur));
}
}
}
}
Floyd
普通版
void Floyd(){
for(
int k=
1;k<=n;k++)
for(
int i=
1;i<=n;i++)
for(
int j=
1;j<=n;j++)
if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j];
}
求最小环
//算最小环
//一个环可以拆成一条链加一条边,
//算floyd的时候保证中间点k的编号比i大比j小,就可以保证首尾不经过k点
void Floyd
_minimum_cycle(){
for(int k=1;k<=n;k++){
for(int i=1;i<k;i++)
for(int j=k+1;j<=n;j++)
ans=min(ans,dis[i][j]+map[i][k]+map[k][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
//有向图求最小环,直接用floyd就可以,以s为起点的环长度为d[
s][
k]+d[
k][
s]
//也可以跑Dijkstra先算从s到所有点的最短距离,再算所有点到s的最短距离
//求以s为终点的单(终点)最短路,把图上所有边反过来就好
最近公共祖先(LCA)
Tarjan
bool flag[maxn],answered[maxn];
vector<pii> qes;
void csh(){
memset(flag,
0.sizeof(flag));
for(
int i=
1;i<=n;i++) fa[i]=i;
memset(head,
0,
sizeof(head));
memset(answered,
0,
sizeof(answered));
}
void Union(
int x,
int y){
fa[find(y)]=find(x);
return;
}
void LCA(
int p,
int f){
for(
int i=head[p];~i;i=e[i].next){
if(e[i].to!=f&&!flag[to]){
LCA(e[i].to,p);
Union(p,e[i].to);
flag[to]=
1;
}
}
}
使用方法:LCA(根节点,
0);
RMQ+DFS(倍增)
void dfs(
int rt){
for(
int i=head[rt];~i;i=e[i].next){
if(!dep[e[i].to]){
dep[e[i].to]=dep[rt]+
1;
p[e[i].to][
0]=rt;
dfs(e[i].to);
}
}
return;
}
void init_bz(){
for(
int j=
1;(
1<<j)<=n;j++)
for(
int i=
1;i<=n;i++)
if(p[i][j-
1]!=-
1)
p[i][j]=p[p[i][j-
1]][j-
1];
return;
}
int LCA(
int a,
int b){
int i,j;
if(dep[a]<dep[b]) swap(a,b);
for(i=
0;(
1<<i)<=dep[a];i++); i--;
for(j=i;j>=
0;j--)
if(dep[a]-(
1<<j)>=dep[b]) a=p[a][j];
if(a==b)
return a;
for(j=i;j>=
0;j--)
if(p[a][j]!=-
1&&p[a][j]!=p[b][j]){
a=p[a][j]; b=p[b][j];
}
return p[a][
0];
}
使用方法:
dfs(
1);
dep[
1]=
0;
p[
1][
0]=
1;
二分图
二分图染色
int col[maxn];
bool flag=
1;
void ran(
int p,
int rt,
int c){
if(col[rt]!=-
1&&col[rt]!=c){
flag=
0;
return;
}
else {
for(
int i=head[rt];i!=
0;i=e[i].next){
int cur=e[i].to;
ran(rt,cur,(c+
1)%
2);
}
return;
}
}
二分图最大匹配(匈牙利算法)
读入优化
inline
int read(){
int x=
0,f=
1; char ch=getchar();
while(ch<
'0'||ch>
'9'){
if(ch==
'-') f=-
1;
ch=getchar();
}
while(ch>=
'0'&&ch<=
'9'){
x=
x*10+ch-
'0'; ch=getchar();
}
return x*f;
}//读入优化来一波~~
NTR算法主体
int nx,ny,match[maxn];
bool vis[maxn],w[maxn][maxn];
bool find(
int x){
for(
int i=
1;i<=ny;i++){
if(!w[x][i]||vis[i])
continue;
vis[i]=
1;
if(match[i]==-
1||find(match[i])){
match[i]=x;
return 1;
}
}
return 0;
}
int suan(){
int ans=
0;
memset(match,-
1,
sizeof(match));
for(
int i=
1;i<=nx;i++){
memset(vis,
0,
sizeof(vis));
if(find(i)) ans++;
}
return ans;
}
int m,a,b;
int main(){
nx=read(); ny=read();
for(
int i=
1;i<=m;i++){
a=read(); b=read();
w[a][b]=
1;
}
int out=suan();
if(out)
printf(
"%d\n",out);
else puts(
"No.");
return 0;
}
二分图最小完备匹配(KM算法)
不会网络流怎么破!!!!!!!!!!!!!
int nx,ny,linky[maxn];
double lack,w[maxn][maxn],lx[maxn],ly[maxn];
bool visx[maxn],visy[maxn];
bool find(
int x){
visx[x]=
1;
for(
int i=
1;i<=ny;i++){
if(visy[i])
continue;
int t=lx[x]+ly[i]-w[x][i];
if(t<
0){
visy[i]=
1;
if(linky[i]==-
1||find(linky[i])){
linky[i]=x;
return 1;
}
}
else if(t<lack) lack=t;
}
return 0;
}
double KM(){
memset(linky,-
1,
sizeof(linky));
for(
int i=
1;i<=ny;i++) ly[i]=
0;
for(
int i=
1;i<=nx;i++){
lx[i]=INF;
for(
int j=
1;j<=ny;j++)
if(w[i][j]>lx[i]) lx[i]=w[i][j];
}
for(
int x=
1;x<=nx;x++){
while(
1){
memset(visx,
0,
sizeof(visx));
memset(visy,
0,
sizeof(visy));
lack=INF;
if(find(x))
break;
for(
int i=
1;i<=ny;i++){
if(visx[i]) lx[i]-=lack;
if(visy[i]) ly[i]+=lack;
}
}
}
int ans=
0;
for(
int i=
1;i<=ny;i++) ans-=w[linky[i]][i];
return ans;
}
拓扑排序
Kahn算法
priority_queue<
int,
vector<int>,greater<
int> > s;
int in[maxn];
vector<int> ans;
void Kahn(){
for(
int i=
1;i<=n;i++)
if(in[i]==
0) s.push(i);
while(!s.empty()){
int cur=s.top(); s.pop(); ans.push_back(cur);
for(
int i=head[cur];i!=
0;i=e[i].next){
int tmp=e[i].to;
in[tmp]--;
if(in[tmp]==
0) s.push(tmp);
}
}
return;
}
强连通分量
%Tarjan
stack<int> s;
bool vis[maxn];
int dfn[maxn],low[maxn],cnt=
0,num=
0;
int qlt[maxn];
vector<int> ans[maxn];
void Tarjan(
int u){
dfn[u]=low[u]=++cnt;
vis[u]=
1;
s.push(u);
for(
int i=head[u];i!=
0;i=e[i].next){
int cur=e[i].to;
if(!vis[cur]){
Tarjan(cur);
low[u]=min(low[u],low[cur]);
}
else if(!qlt[cur]) {
low[u]=min(low[u],low[cur]);
}
}
if(dfn[u]==low[u]){
num++;
while(
1){
int tmp=s.top(); s.pop();
qlt[tmp]=num;
if(tmp==u)
break;
}
}
}
转载于:https://www.cnblogs.com/leotan0321/p/6081364.html