【图论】基础算法及模板

一)单源最短路问题

测试: http://www.51nod.com/Challenge/Problem.html#problemId=2673

  • Dijkstra
const int NN=100100;
const int inf=0x3f3f3f3f;

int dis[NN],vis[NN];
struct qnode{
    int v,dst;
    qnode(){}
    qnode(int vv,int dd){
        v=vv;dst=dd;
    }
    bool operator <(const qnode q)const{
        return dst>q.dst;
    }
};
vector<qnode> ve[NN];

void Dijkstra(int start){
    priority_queue<qnode> que;
    while(!que.empty()) que.pop();
    for(int i=1;i<=n;i++) dis[i]=inf;
    que.push(qnode(start,0));
    dis[start]=0;
    while(!que.empty()){
        int u=que.top().v;
        que.pop();
        if(vis[u]) continue;vis[u]=1;
        for(qnode &t:ve[u]){
            if(dis[u]+t.dst<dis[t.v]){
                dis[t.v]=dis[u]+t.dst;
                que.push(qnode(t.v,dis[t.v]));
            }
        }
    }
}
  • Spfa
const int NN=100100;
const int inf=0x3f3f3f3f;

struct node{
    int v,dst;
    node(){}
    node(int vv,int dd){
        v=vv;dst=dd;
    }
};
vector<node> ve[NN];
int dis[NN],inque[NN],incnt[NN];

bool Spfa(int start){
    queue<int> que;
    while(!que.empty()) que.pop();
    for(int i=1;i<=n;i++) dis[i]=inf;
    que.push(start);dis[start]=0;
    while(!que.empty()){
        int u=que.front();
        que.pop();
        inque[u]=0;
        for(node &t:ve[u]){
            if(dis[u]+t.dst<dis[t.v]){
                dis[t.v]=dis[u]+t.dst;
                if(!inque[t.v]){
                    que.push(t.v),inque[t.v]=1;
                    if(++incnt[t.v]>=n) return false;
                }
            }
        }
    }
    return true;
}

二)最小生成树问题

测试: http://www.51nod.com/Challenge/Problem.html#problemId=1212

  • Kruscal
const int NN=100100;
const int inf=0x3f3f3f3f;

struct Edge{
    int x,y,dst;
    bool operator <(const Edge e)const{
        return dst<e.dst;
    }
};

Edge edge[NN];
int sum,fa[NN];

int father(int x){
    if(fa[x]==x) return x;
    return fa[x]=father(fa[x]);
}

void Kruscal(){
    for(int i=1;i<=n;i++) fa[i]=i;
    sort(edge+1,edge+m+1);
    for(int i=1;i<=m;i++){
        int x=father(edge[i].x),y=father(edge[i].y);
        if(x==y) continue;
        sum+=edge[i].dst;
        fa[x]=y;
    }
}
  • Prime
const int NN=100100;
const int inf=0x3f3f3f3f;

struct qnode{
    int v,dst;
    qnode(){}
    qnode(int vv,int dd){
        v=vv;dst=dd;
    }
    bool operator <(const qnode q)const{
        return dst>q.dst;
    }
};

vector<qnode> ve[NN];
int sum,vis[NN];

void Prime(){
    priority_queue<qnode> que;
    while(!que.empty()) que.pop();
    que.push(qnode(1,0));
    while(!que.empty()){
        qnode tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(vis[u]) continue;
        vis[u]=1;
        sum+=tmp.dst;
        for(qnode &t:ve[u]){
            if(!vis[t.v]) que.push(qnode(t.v,t.dst));
        }
    }
}

三)拓扑排序问题

测试:http://acm.hdu.edu.cn/showproblem.php?pid=1285

  • Topo
const int NN=100100;
const int inf=0x3f3f3f3f;

int inp[NN],ans[NN],ans_size;
vector<int> ve[NN];

//对不分先后的情况,先输出序号较小的节点
//视题目要求,可以自定义结构体类型加入优先队列
bool Topo(){
    priority_queue<int,vector<int>,greater<int> > que;
    while(!que.empty()) que.pop();
    for(int i=1;i<=n;i++) if(inp[i]==0) que.push(i);
    while(!que.empty()){
        int u=que.top();que.pop();
        ans[++ans_size]=u;
        for(int v:ve[u]){
            if(--inp[v]==0) que.push(v);
        }
    }
    if(ans_size!=n) return false;
    return true;
}

四)强连通问题

测试:https://www.luogu.com.cn/problem/P2341

  • Tajan
const int NN=100100;
const int inf=0x3f3f3f3f;

int low[NN],dfn[NN],belong[NN],num[NN],sta[NN],oup[NN];
int top,t,idx,scc_size;
vector<int> ve[NN];

void Tarjan(int u){
    low[u]=dfn[u]=++idx;
    sta[++top]=u;
    for(int v:ve[u]){
        if(!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]);
        if(!belong[v]) low[u]=min(low[u],low[v]);
    }
    if(low[u]==dfn[u]){
        scc_size++;
        do{
            t=sta[top--];
            belong[t]=scc_size;
            num[scc_size]++;
        }while(u!=t);
    }
}

int solve(){
    for(int i=1;i<=n;i++)
        if(!dfn[i]) Tarjan(i);
    for(int u=1;u<=n;u++){
        bool flag=false;
        for(int v:ve[u])
            if(belong[v]!=belong[u]) oup[belong[u]]=true;
    }
    int ans=0,cnt=0;
    for(int i=1;i<=scc_size;i++){
        if(!oup[i]) ans=num[i],cnt++;
    }
    if(cnt==1) return ans;
    else return 0;
}

五)二分图匹配问题

测试:http://www.51nod.com/Challenge/Problem.html#problemId=2006

  • Hungary
const int NN=100100;
const int inf=0x3f3f3f3f;

vector<int> ve[NN];
int mat[NN],vis[NN],sum;

int find(int u){
    for(int v:ve[u]){
        if(vis[v]) continue;
        vis[v]=true;
        if(!mat[v]||find(mat[v])) {
            mat[v]=u;
            return true;
        }
    }
    return false;
}

int Hungary(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++) vis[j]=0;
        sum+=find(i);
    }
    return sum;
}

六)最大流问题

测试:https://loj.ac/problem/101

  • Dinic
const int NN=100100;
const ll inf=0x3f3f3f3f3f;

struct node{
    int v,cap,id;
    node(){}
    node(int _v,int _cap,int _id){
        v=_v;cap=_cap;id=_id;
    }
};

vector<node> ve[NN];
int dfn[NN],cur[NN],S,T;

bool bfs(int S){
    queue<int> que;
    while(!que.empty()) que.pop();
    for(int i=1;i<=n;i++) dfn[i]=0;
    dfn[S]=1;que.push(S);
    while(!que.empty()){
        int u=que.front();que.pop();
        for(node &t:ve[u]) if(!dfn[t.v]&&t.cap){
            dfn[t.v]=dfn[u]+1;
            que.push(t.v);
        }
    }
    return dfn[T];
}

ll dfs(int u,int flow){
    if(u==T) return flow;
    ll max_flow=0;
    for(;cur[u]<ve[u].size();cur[u]++){
        node &t=ve[u][cur[u]];
        int v=t.v;
        if(t.cap&&dfn[v]==dfn[u]+1){
            tmp=dfs(v,min(flow,t.cap));
            flow-=tmp;t.cap-=tmp;ve[v][t.id].cap+=tmp;
            max_flow+=tmp;
            if(flow==0) return max_flow;
        }
    }
    return max_flow;
}

ll Dinic(int S){
    ll sum=0;
    while(bfs(S)){
        for(int i=1;i<=n;i++) cur[i]=0;
        while(ll t=dfs(S,inf)) sum+=t;
    }
    return sum;
}

你可能感兴趣的:(图论,图论,模板)