zoukankan      html  css  js  c++  java
  • 【模板】图论

    最小生成树:http://www.cnblogs.com/cangT-Tlan/p/7794372.html

    次小生成树:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct nond{
        int x,y,z;
    }edge[400000];
    int T,N,M,x,y,z,fa[200000],num,ans[200000];
    int tot,bns,k,answer=0x7f7f7f7f;
    int cmp(nond aa,nond bb){
        return aa.z<bb.z;
    }
    int find(int x){
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    int main(){
        freopen("mst2.in","r",stdin);
        freopen("mst2.out","w",stdout);
        cin>>N>>M;
        for(int i=1;i<=M;i++){
            cin>>x>>y>>z;
            edge[i].x=x;
            edge[i].y=y;
            edge[i].z=z;
        }
        sort(edge+1,edge+1+M,cmp);
        for(int i=1;i<=N;i++)    fa[i]=i;
        for(int i=1;i<=M;i++){
            int dx=find(edge[i].x);
            int dy=find(edge[i].y);
            if(dx!=dy){
                fa[dx]=dy;
                tot++;
                ans[tot]=i;
                bns+=edge[i].z;
            }
            if(tot==N-1)    break;
        }
        for(int i=1;i<=tot;i++){
            k=0;num=0;
            for(int j=1;j<=N;j++)    fa[j]=j;
            sort(edge+1,edge+1+M,cmp);
            for(int j=1;j<=M;j++){
                if(j==ans[i])    continue;
                int dx=find(edge[j].x);
                int dy=find(edge[j].y);
                if(dx!=dy){
                    fa[dx]=dy;
                    num++;
                    k+=edge[j].z;
                }
                if(num==N-1)    break;
            }
            if(num==N-1&&k!=bns) answer=min(k,answer);
        }
        cout<<answer;
    }
    次小生成树

    最短路:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<deque>
    #define MAXN 500010
    using namespace std;
    deque<int>que;
    int n,m,s,vis[MAXN],num[MAXN],dis[MAXN];
    int tot,to[MAXN],from[MAXN],net[MAXN],cap[MAXN];
    void add(int u,int v,int w){
        to[++tot]=v;net[tot]=from[u];cap[tot]=w;from[u]=tot;
    }
    bool spfa(int s){
        for(int i=1;i<=n;i++)    dis[i]=2147483647;
        que.push_back(s);
        vis[s]=1;num[s]++;dis[s]=0;
        while(!que.empty()){
            int now=que.front();
            que.pop_front();
            vis[now]=0;
            for(int i=from[now];i;i=net[i])
                if(dis[to[i]]>dis[now]+cap[i]){
                    dis[to[i]]=dis[now]+cap[i];
                    if(!vis[to[i]]){
                        if(dis[to[i]]>dis[que.front()])
                            que.push_back(to[i]);
                        else
                            que.push_front(to[i]); 
                        vis[to[i]]=1;
                        num[to[i]]++;
                        if(num[to[i]]>n)
                            return false;
                    }
                }
        }
        return true;
    }
    int main(){
        cin>>n>>m>>s;
        for(int i=1;i<=m;i++){
            int u,v,w;
            cin>>u>>v>>w;
            add(u,v,w);
        }
        if(spfa(s))
            for(int i=1;i<=n;i++)
                cout<<dis[i]<<" ";
    }
    spfa 最短路
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define MAXN 500010
    using namespace std;
    struct nond{
        int number,dis;
        bool operator < (nond b) const{
            return dis>b.dis;
        }
    };
    int n,m,s,dis[MAXN];
    int tot,to[MAXN],net[MAXN],from[MAXN],cap[MAXN];
    void add(int u,int v,int w){
        to[++tot]=v;net[tot]=from[u];cap[tot]=w;from[u]=tot;
    }
    void dijkstra(int x){
        priority_queue<nond>que;
        for(int i=1;i<=n;i++)    dis[i]=2147483647;
        dis[x]=0;
        que.push((nond){x,0});
        while(!que.empty()){
            nond now=que.top();
            que.pop();
            if(dis[now.number]!=now.dis)    continue;
            for(int i=from[now.number];i;i=net[i])
                if(dis[to[i]]>dis[now.number]+cap[i]){
                    dis[to[i]]=dis[now.number]+cap[i];
                    que.push((nond){to[i],dis[to[i]]});
                }
        }    
    }
    int main(){
        cin>>n>>m>>s;
        for(int i=1;i<=m;i++){
            int u,v,w;
            cin>>u>>v>>w;
            add(u,v,w);
        }
        dijkstra(s);
        for(int i=1;i<=n;i++)
            cout<<dis[i]<<" ";
    }#include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define MAXN 500010
    using namespace std;
    struct nond{
        int number,dis;
        bool operator < (nond b) const{
            return dis>b.dis;
        }
    };
    int n,m,s,dis[MAXN];
    int tot,to[MAXN],net[MAXN],from[MAXN],cap[MAXN];
    void add(int u,int v,int w){
        to[++tot]=v;net[tot]=from[u];cap[tot]=w;from[u]=tot;
    }
    void dijkstra(int x){
        priority_queue<nond>que;
        for(int i=1;i<=n;i++)    dis[i]=2147483647;
        dis[x]=0;
        que.push((nond){x,0});
        while(!que.empty()){
            nond now=que.top();
            que.pop();
            if(dis[now.number]!=now.dis)    continue;
            for(int i=from[now.number];i;i=net[i])
                if(dis[to[i]]>dis[now.number]+cap[i]){
                    dis[to[i]]=dis[now.number]+cap[i];
                    que.push((nond){to[i],dis[to[i]]});
                }
        }    
    }
    int main(){
        cin>>n>>m>>s;
        for(int i=1;i<=m;i++){
            int u,v,w;
            cin>>u>>v>>w;
            add(u,v,w);
        }
        dijkstra(s);
        for(int i=1;i<=n;i++)
            cout<<dis[i]<<" ";
    }
    heap优化的dij
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 200010
    using namespace std;
    int T,n,m,tot,vist;
    int vis[MAXN],head[MAXN],dis[MAXN];
    int to[MAXN*2],cap[MAXN*2],net[MAXN*2];
    int add(int u,int v,int w){
        to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
    }
    int spfa(int now){
        vis[now]=1;
        for(int i=head[now];i;i=net[i])
            if(dis[to[i]]>dis[now]+cap[i]){
                dis[to[i]]=dis[now]+cap[i];
                if(vis[to[i]]||spfa(to[i])){
                    vis[to[i]]=0;
                    return 1;
                }
            }
        vis[now]=0;
        return 0;
    }
    int main(){
        //freopen("a.in","r",stdin);
        scanf("%d",&T);
        while(T--){
            tot=0;vist=0;
            memset(to,0,sizeof(to));
            memset(cap,0,sizeof(cap));
            memset(net,0,sizeof(net));
            memset(dis,0,sizeof(dis));
            memset(vis,0,sizeof(vis));
            memset(head,0,sizeof(head));
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++){
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,z);
                if(z>0) add(y,x,z);
            }
            for(int i=1;i<=n;i++)
                if(spfa(i)){
                    cout<<"YE5"<<endl;
                    vist=1;
                    break;
                }
            if(!vist) cout<<"N0"<<endl;
        }
        return 0;
    }
    spfa的dfs判负环

    (二分图匹配)匈牙利算法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int MAXN=1010;
    using namespace std;
    int n,m,e,map[MAXN][MAXN];
    int ans,use[MAXN],girl[MAXN];
    bool find(int x){
        for(int j=1;j<=m;j++)
            if(map[x][j]==1&&use[j]==0){
                use[j]=1;
                if(girl[j]==0||find(girl[j])){
                    girl[j]=x;
                    return 1;
                }
            }
        return 0;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&e);
        for(int i=1;i<=e;i++){
            int x,y;
            scanf("%d%d",&x,&y); 
            if(x>m||y>m) continue;
            map[x][y]=1;
        }    
        for(int i=1;i<=n;i++){
            memset(use,0,sizeof(use));
            if(find(i))    ans++;
        }
        printf("%d",ans);
    }
    匈牙利

    tarjin:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,m;
    int sumcol;
    int tot,tim,top;
    int col[MAXN];
    int to[MAXN],net[MAXN],head[MAXN];
    int low[MAXN],dfn[MAXN],vis[MAXN],stack[MAXN],visstack[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
    }
    void tarjin(int now){
        stack[++top]=now;
        low[now]=dfn[now]=++tim;
        vis[now]=1;
        visstack[now]=1;
        for(int i=head[now];i;i=net[i])
            if(visstack[to[i]])
                low[now]=min(low[now],dfn[to[i]]);
            else if(!vis[to[i]]){
                tarjin(to[i]);
                low[now]=min(low[now],low[to[i]]);
            }
        if(dfn[now]==low[now]){
            sumcol++;
            col[now]=sumcol;
            while(stack[top]!=now){
                col[stack[top]]=sumcol;
                visstack[stack[top]]=0;
                top--;
            }
            visstack[now]=0;
            top--;
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])
                tarjin(i);
        cout<<sumcol;
    }
    tarjin求强连通分量的个数
    #include<map>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    queue<int>que;
    map<int,int>ma[MAXN];
    int n,m;
    int sumcol,ans;
    int tot,tot1,tim,top;
    int col[MAXN],into[MAXN];
    int val[MAXN],cost[MAXN],dis[MAXN];
    int to[MAXN],net[MAXN],head[MAXN];
    int to1[MAXN],net1[MAXN],head1[MAXN];
    int low[MAXN],dfn[MAXN],vis[MAXN],stack[MAXN],visstack[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
    }
    void add1(int u,int v){
        to1[++tot1]=v;net1[tot1]=head1[u];head1[u]=tot1;
    }
    void tarjin(int now){
        stack[++top]=now;
        low[now]=dfn[now]=++tim;
        vis[now]=1;
        visstack[now]=1;
        for(int i=head[now];i;i=net[i])
            if(visstack[to[i]])
                low[now]=min(low[now],dfn[to[i]]);
            else if(!vis[to[i]]){
                tarjin(to[i]);
                low[now]=min(low[now],low[to[i]]);
            }
        if(dfn[now]==low[now]){
            sumcol++;
            col[now]=sumcol;
            while(stack[top]!=now){
                col[stack[top]]=sumcol;
                visstack[stack[top]]=0;
                top--;
            }
            visstack[now]=0;
            top--;
        }
    }
    void spfa(int s){
        memset(dis,0,sizeof(dis));
        memset(vis,0,sizeof(vis));
        while(!que.empty())    que.pop();
        dis[s]=cost[s];
        vis[s]=1;
        que.push(s);
        while(!que.empty()){
            int now=que.front();
            que.pop();
            vis[now]=0;
            for(int i=head1[now];i;i=net1[i])
                if(dis[to1[i]]<dis[now]+cost[to1[i]]){
                    dis[to1[i]]=dis[now]+cost[to1[i]];
                    if(!vis[to1[i]]){
                        vis[to1[i]]=1;
                        que.push(to1[i]);
                    }
                }
        }
        for(int i=1;i<=sumcol;i++)    ans=max(ans,dis[i]);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)    scanf("%d",&val[i]);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])
                tarjin(i);
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=net[j])
                if(col[i]!=col[to[j]])
                    if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                        ma[col[i]][col[to[j]]]=1;
                        into[col[to[j]]]++;
                        add1(col[i],col[to[j]]);
                    }
        for(int i=1;i<=n;i++)    cost[col[i]]+=val[i];
        for(int i=1;i<=sumcol;i++)
            if(!into[i])
                spfa(i);
        cout<<ans;
    }
    tarjin缩点
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    int n,m,ans;
    int tot=1,tim;
    int cutdian[MAXN],cutbian[MAXN];
    int to[MAXN*2],net[MAXN*2],head[MAXN];
    int low[MAXN],dfn[MAXN],vis[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
        to[++tot]=u;net[tot]=head[v];head[v]=tot;
    }
    void tarjin(int now,int pre){
        low[now]=dfn[now]=++tim;
        vis[now]=1;
        int sum=0;
        bool boo=0;
        for(int i=head[now];i;i=net[i])
            if((i^1)!=pre)
                if(!vis[to[i]]){
                    sum++;
                    tarjin(to[i],i);
                    if(low[to[i]]>dfn[now])    cutbian[i/2]=1;
                    if(low[to[i]]>=dfn[now])    boo=1;
                    low[now]=min(low[now],low[to[i]]);
                }
                else    low[now]=min(low[now],dfn[to[i]]);
        if(pre==-1){
            if(sum>1)    cutdian[now]=1;
        }
        else if(boo==1)    cutdian[now]=1;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])
                tarjin(i,-1);
        for(int i=1;i<=n;i++)
            if(cutdian[i])    ans++;
        cout<<ans<<endl;
        for(int i=1;i<=n;i++)
            if(cutdian[i])
                cout<<i<<" ";
    }
    tarjin割边割点

    最近公共祖先:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 500010
    using namespace std;
    int n,m,s,tot;
    int to[MAXN*2],net[MAXN*2],head[MAXN];
    int dad[MAXN],deep[MAXN],siz[MAXN],top[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
        to[++tot]=u;net[tot]=head[v];head[v]=tot;
    }
    void dfs(int now){
        siz[now]=1;
        deep[now]=deep[dad[now]]+1;
        for(int i=head[now];i;i=net[i])
            if(to[i]!=dad[now]){
                dad[to[i]]=now;
                dfs(to[i]);
                siz[now]+=siz[to[i]];
            }
    }
    void dfs1(int x){
        int t=0;
        if(!top[x])    top[x]=x;
        for(int i=head[x];i;i=net[i])
            if(to[i]!=dad[x]&&siz[to[i]]>siz[t])
                t=to[i];
        if(t){
            top[t]=top[x];
            dfs1(t);
        }
        for(int i=head[x];i;i=net[i])
            if(to[i]!=dad[x]&&t!=to[i])
                dfs1(to[i]);
    }
    int lca(int x,int y){
        for(;top[x]!=top[y];){
            if(deep[top[x]]<deep[top[y]])
                swap(x,y);
            x=dad[top[x]];
        }
        if(deep[x]>deep[y])
            swap(x,y);
        return x;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        dfs(s);
        dfs1(s);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            cout<<lca(u,v)<<endl;
        }
    }
    树链剖分
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 500010
    using namespace std;
    int n,m,s,tot;
    int dad[MAXN][20],deep[MAXN];
    int to[MAXN*2],net[MAXN*2],head[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
        to[++tot]=u;net[tot]=head[v];head[v]=tot;
    }
    void dfs(int now){
        deep[now]=deep[dad[now][0]]+1;
        for(int i=0;dad[now][i];i++)
            dad[now][i+1]=dad[dad[now][i]][i];
        for(int i=head[now];i;i=net[i])
            if(!deep[to[i]]){
                dad[to[i]][0]=now;
                dfs(to[i]);
            }
    }
    int lca(int x,int y){
        if(deep[x]>deep[y])    swap(x,y); 
        for(int i=18;i>=0;i--)
            if(deep[dad[y][i]]>=deep[x])
                y=dad[y][i];
        if(x==y)    return x;
        for(int i=18;i>=0;i--)
            if(dad[x][i]!=dad[y][i]){
                x=dad[x][i];
                y=dad[y][i];
            }
        return dad[x][0];
    }
    int main(){
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        dfs(s);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            cout<<lca(u,v)<<endl;
        }
    }
    倍增

    网络流:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define NAXN 10001
    #define MAXN 100001
    using namespace std;
    int n,m,s,t;
    int tot=1,ans;
    int cur[NAXN],lev[NAXN];
    int to[MAXN*2],net[MAXN*2],cap[MAXN*2],head[NAXN];
    void add(int u,int v,int w){
        to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
        to[++tot]=u;cap[tot]=0;net[tot]=head[v];head[v]=tot;
    }
    bool bfs(){
        queue<int>que;
        for(int i=1;i<=n;i++){
            lev[i]=-1;
            cur[i]=head[i];
        }
        lev[s]=0;
        que.push(s);
        while(!que.empty()){
            int now=que.front();
            que.pop();
            for(int i=head[now];i;i=net[i])
                if(lev[to[i]]==-1&&cap[i]>0){
                    lev[to[i]]=lev[now]+1;
                    que.push(to[i]);
                    if(to[i]==t)    return true;
                }
        }
        return false;
    }
    int dinic(int now,int flow){
        if(now==t)    return flow;
        int rest=0,detal;
        for(int & i=cur[now];i;i=net[i])
            if(cap[i]>0&&lev[to[i]]==lev[now]+1){
                detal=dinic(to[i],min(flow-rest,cap[i]));
                if(detal){
                    rest+=detal;
                    cap[i]-=detal;
                    cap[i^1]+=detal;
                    if(rest==flow)    break;
                }
            }
        if(rest!=flow)    lev[now]=-1;
        return rest;
    }
    int main(){
        cin>>n>>m>>s>>t;
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        while(bfs())
            ans+=dinic(s,0x7fffffff);
        cout<<ans;
    }
    网络流最大流
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define NAXN 10001
    #define MAXN 100001
    using namespace std;
    int n,m,s,t;
    int tot=1,ans;
    int cur[NAXN],lev[NAXN];
    int to[MAXN*2],net[MAXN*2],cap[MAXN*2],head[NAXN];
    void add(int u,int v,int w){
        to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
        to[++tot]=u;cap[tot]=0;net[tot]=head[v];head[v]=tot;
    }
    bool bfs(){
        queue<int>que;
        for(int i=1;i<=n;i++){
            lev[i]=-1;
            cur[i]=head[i];
        }
        lev[s]=0;
        que.push(s);
        while(!que.empty()){
            int now=que.front();
            que.pop();
            for(int i=head[now];i;i=net[i])
                if(lev[to[i]]==-1&&cap[i]>0){
                    lev[to[i]]=lev[now]+1;
                    que.push(to[i]);
                    if(to[i]==t)    return true;
                }
        }
        return false;
    }
    int dinic(int now,int flow){
        if(now==t)    return flow;
        int rest=0,detal;
        for(int & i=cur[now];i;i=net[i])
            if(cap[i]>0&&lev[to[i]]==lev[now]+1){
                detal=dinic(to[i],min(flow-rest,cap[i]));
                if(detal){
                    rest+=detal;
                    cap[i]-=detal;
                    cap[i^1]+=detal;
                    if(rest==flow)    break;
                }
            }
        if(rest!=flow)    lev[now]=-1;
        return rest;
    }
    int main(){
        cin>>n>>m>>s>>t;
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        while(bfs())
            ans+=dinic(s,0x7fffffff);
        cout<<ans;
    }
    网络流最小割

     

  • 相关阅读:
    【数据结构】算法 Tree Sub Structure 树的子结构
    【数据结构】算法 Binary Search Tree find Kth largest Node 二叉搜索树的第k大节点
    【数据结构】算法 Count Complete Tree Nodes 完全二叉树的节点个数
    【数据结构】算法 合并K个有序链表Merge k Sorted Lists
    JVisualVM 插件安装中出现网络问题
    [ISSUE] Logback TimeBasedRollingPolicy not rolling every day.
    【数据结构】算法 计算数组中的逆序对
    JQ为元素添加class
    时间戳转换成日期
    JS拖拽
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7794935.html
Copyright © 2011-2022 走看看