一、最短路
1.dij
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
for(int i=1;i<=n;i++)dis[i]=inf;
dis[s]=0; q.push(make_pair(0,s));
while(q.size()){
int x=q.top().second;q.pop();
if(vis[x])continue;
vis[x]=1;
for(int i=head[x];i;i=e[i].nxt){
int t=e[i].to;
if(dis[t]>dis[x]+e[i].w){
dis[t]=dis[x]+e[i].w;
q.push(make_pair(dis[t],t));
}
}
}
2.spfa
queue<int> q;
for(int i=1;i<=n;i++)dis[i]=inf,vis[i]=0;
q.push(s);dis[s]=0;vis[s]=1;
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!vis[v])q.push(v),vis[v]=1;
}
}
}
二、生成树
1.最小生成树
int get(int x){
return fa[x]==x?x:fa[x]=get(fa[x]);
}
sort(e,e+m,cmp);
for(int i=0;i<m;i++){
fx=get(e[i].x);
fy=get(e[i].y);
if(fx==fy)continue;
ans+=e[i].w;
fa[fx]=fy;
}
三、Tarjan算法
有向图缩点
void tarjan(int u){
dfn[u]=low[u]=++timber;s[++top]=u;vis[u]=1;
for(int i=head[u],v;i;i=e[i].nxt){
v=e[i].to;
if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]);
else if(vis[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
sz++;
while(top){
int x=s[top--];
id[x]=sz;vis[x]=0;
if(x==u)break;
}
}
}
int main(){
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
}
求无向图的割点
void tarjan(int u){
int rd=0;
dfn[u]=low[u]=++timber;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!dfn[v]){
fa[v]=fa[u];tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]&&u!=fa[u])vis[u]=1;
if(u==fa[u])rd++;
}
low[u]=min(low[u],dfn[v]);
}
if(u==fa[u]&&rd>=2)vis[fa[u]]=1;
}
int main(){
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++)if(vis[i])cout<<i<<" ";
}
四、网络流
二分图最大匹配(匈牙利算法)(链接)
#include <bits/stdc++.h>
using namespace std;
int n,m,e,ans,matched[2005];
bool vis[2005][2005],ask[2005];
bool found(int x){
for(int i=1;i<=m;i++)
if(vis[x][i]){
if(ask[i])continue;
ask[i]=1;
if(!matched[i]||found(matched[i])){
matched[i]=x;return true;
}
}
return false;
}
void match(){
memset(matched,0,sizeof(matched));
for(int i=1;i<=n;i++){
memset(ask,0,sizeof(ask));
if(found(i))ans++;
}
}
int main(){
scanf("%d%d%d",&n,&m,&e);
for(int i=1,x,y;i<=e;i++)scanf("%d%d",&x,&y),vis[x][y]=1;
match();
printf("%d\n",ans);
return 0;
}
网络最大流Dinic (链接)
#include <bits/stdc++.h>
using namespace std;
const long long inf=2e9;
int n,m,s,t,u,v;
long long w,ans,dis[520010];
int tot=1,now[520010],head[520010];
struct node {int to,nxt;long long val;}e[520010];
void add(int u,int v,long long w) {
e[++tot].to=v;e[tot].val=w;e[tot].nxt=head[u];head[u]=tot;
}
inline int bfs() {
for(int i=1;i<=n;i++)dis[i]=inf;
queue<int> q;
q.push(s);dis[s]=0;now[s]=head[s];
while(!q.empty()) {
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].nxt) {
int v=e[i].to;
if(e[i].val>0&&dis[v]==inf) {
q.push(v);
now[v]=head[v];
dis[v]=dis[x]+1;
}
}
}
if(dis[t]==inf)return 0;
return 1;
}
inline int dfs(int x,long long sum){
if(x==t) return sum;
long long k,res=0;
for(int i=now[x];i&∑i=e[i].nxt) {
now[x]=i;int v=e[i].to;
if(e[i].val>0&&(dis[v]==dis[x]+1)) {
k=dfs(v,min(sum,e[i].val));
if(k==0)dis[v]=inf;
e[i].val-=k;e[i^1].val+=k;
res+=k;sum-=k;
}
}
return res;
}
int main() {
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++)
scanf("%d%d%lld",&u,&v,&w),add(u,v,w),add(v,u,0);
while(bfs())ans+=dfs(s,inf);
printf("%lld",ans);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int n,m,s,t,cnt=1,head[50005],dis[50005],incf[50005],pre[50005],maxflow,mincost;
bool vis[50005];
struct node{int nxt,to,w,val;}e[100005];
inline int read(){
int X=0;bool flag=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')flag=0;ch=getchar();}
while(ch>='0'&&ch<='9'){X=(X<<1)+(X<<3)+ch-'0';ch=getchar();}
if(flag)return X;
return ~(X-1);
}
void insert(int u,int v,int w,int val){
e[++cnt].nxt=head[u];e[cnt].to=v;e[cnt].w=w;e[cnt].val=val;head[u]=cnt;
}
bool spfa(){
for(int i=1;i<=n;i++)dis[i]=1e9,vis[i]=0;
queue<int> q;
q.push(s);dis[s]=0;vis[s]=1;incf[s]=1<<30;
while(!q.empty()){
int u=q.front();vis[u]=0;q.pop();
for(int i=head[u];i;i=e[i].nxt){
if(!e[i].w)continue;
int v=e[i].to;
if(dis[v]>dis[u]+e[i].val){
dis[v]=dis[u]+e[i].val;
incf[v]=min(incf[u],e[i].w);
pre[v]=i;
if(!vis[v])vis[v]=1,q.push(v);
}
}
}
if(dis[t]==1e9)return 0;
return 1;
}
void dinic(){
while(spfa()){
int x=t;
maxflow+=incf[t];
mincost+=dis[t]*incf[t];
while(x!=s){
int i=pre[x];
e[i].w-=incf[t];e[i^1].w+=incf[t];
x=e[i^1].to;
}
}
}
int main(){
n=read();m=read();s=read();t=read();
for(int i=1,u,v,w,x;i<=m;i++){
u=read();v=read();w=read();x=read();
insert(u,v,w,x);insert(v,u,0,-x);
}
dinic();
printf("%d %d\n",maxflow,mincost);
return 0;
}
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int n,m,q;
namespace maxflow{
int s,t,head[10005],cnt=1,dis[10005],now[10005],ans;
struct edge{int to,w,nxt;} e[10005];
void insert(int u,int v,int w){
e[++cnt].nxt=head[u];e[cnt].to=v;e[cnt].w=w;head[u]=cnt;
}
void init(int ss,int tt){
for(int i=2;i<=cnt;i+=2)e[i].w=e[i].w+e[i^1].w,e[i^1].w=0;s=ss,t=tt;
}
bool bfs(){
memset(dis,0x3f,sizeof(dis));
queue<int> q;
q.push(s);dis[s]=0;now[s]=head[s];
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].nxt){
int v=e[i].to;
if(e[i].w>0&&dis[v]==inf){
now[v]=head[v];
dis[v]=dis[x]+1;
q.push(v);
if(v==t) return 1;
}
}
}
return 0;
}
int dfs(int x,int sum){
if(x==t) return sum;
int k,res=0;
for(int i=now[x];i&∑i=e[i].nxt){
now[x]=i;int v=e[i].to;
if(e[i].w>0&&dis[v]==dis[x]+1){
k=dfs(v,min(sum,e[i].w));
if(k==0) dis[v]=inf;
e[i].w-=k,e[i^1].w+=k;
res+=k;sum-=k;
}
}
return res;
}
int dinic(){
int ans=0;
while(bfs())ans+=dfs(s,inf);
return ans;
}
}
namespace tree{
int head[10005],cnt,id[10005],t1[10005],t2[10005],dep[10005],fa[10005][15],minx[10005][15];
struct edge{int to,w,nxt;} e[10005];
void insert(int u,int v,int w){
e[++cnt].nxt=head[u];e[cnt].to=v;e[cnt].w=w;head[u]=cnt;
}
void init(){for(int i=1;i<=n;i++) id[i]=i;memset(minx,0x3f,sizeof(minx));}
void build(int l,int r){
if(l==r) return;
maxflow::init(id[l],id[l+1]);int c=maxflow::dinic();
insert(id[l],id[l+1],c);insert(id[l+1],id[l],c);
int cnt1=0,cnt2=0;
for(int i=l;i<=r;i++){
if(maxflow::dis[id[i]]<inf) t1[++cnt1]=id[i];
else t2[++cnt2]=id[i];
}
for(int i=l;i<l+cnt1;i++) id[i]=t1[i-l+1];
for(int i=l+cnt1;i<=r;i++) id[i]=t2[i-l-cnt1+1];
build(l,l+cnt1-1),build(l+cnt1,r);
}
void dfs(int x,int f){
dep[x]=dep[f]+1,fa[x][0]=f;
for(int i=1;i<10;i++){
fa[x][i]=fa[fa[x][i-1]][i-1];
minx[x][i]=min(minx[x][i-1],minx[fa[x][i-1]][i-1]);
}
for(int i=head[x];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
minx[v][0]=e[i].w;
dfs(v,x);
}
}
void prep(){init(),build(1,n),dfs(1,0);}
int query(int u,int v){
int ans=inf;
if(dep[u]<dep[v])swap(u,v);
for(int i=10;i>=0;i--)
if(dep[fa[u][i]]>=dep[v])
ans=min(ans,minx[u][i]),u=fa[u][i];
if(u==v) return ans;
for(int i=10;i>=0;i--)
if(fa[u][i]!=fa[v][i])
ans=min(ans,min(minx[u][i],minx[v][i])),u=fa[u][i],v=fa[v][i];
ans=min(ans,min(minx[u][0],minx[v][0]));
return ans;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v,w;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
maxflow::insert(u,v,w);maxflow::insert(v,u,0);
maxflow::insert(v,u,w);maxflow::insert(u,v,0);
}
tree::prep();scanf("%d",&q);
for(int i=1,u,v;i<=q;i++){
scanf("%d%d",&u,&v);
printf("%d\n",tree::query(u,v));
}
return 0;
}