zoukankan      html  css  js  c++  java
  • 一些图论模板

    1.单源最短路

    //Twenty
    #include<cstdio>
    #include<iostream> 
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    int n,m,maxl=1e9,x,y,s,t,vis[110];
    double a[110],b[110],f[110][110],dis[110];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        cin>>a[i]>>b[i];
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        f[i][j]=maxl;
        scanf("%d",&m);
        for(int i=1;i<=m;i++) {
            scanf("%d%d",&x,&y);
            f[x][y]=f[y][x]=sqrt(pow((a[x]-a[y]),2)+pow((b[x]-b[y]),2));
        }
        scanf("%d%d",&s,&t);
        for(int i=1;i<=n;i++)
        dis[i]=f[s][i];
        dis[s]=0;
        for(int i=1;i<=n;i++) {
         double maxn=1e9;
         int k=0;
         for(int j=1;j<=n;j++)
         if(dis[j]<maxn&&!vis[j]){
               maxn=dis[j];
               k=j;
        }
        if(k==0)break;
        else{
        vis[k]=1;
        for(int j=1;j<=n;j++){
         if(dis[k]+f[k][j]<dis[j])
         dis[j]=dis[k]+f[k][j];
        }
        }  
        }
        printf("%.2lf",dis[t]);
        return 0;
    }
    dijkstra
    //Twenty
    #include<cstdio>
    #include<iostream> 
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    int n,m,maxl=1e9,x,y,s,t,vis[110];
    double a[110],b[110],f[110][110],dis[110];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        cin>>a[i]>>b[i];
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        f[i][j]=maxl;
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            f[x][y]=f[y][x]=sqrt(pow((a[x]-a[y]),2)+pow((b[x]-b[y]),2));
        }
        scanf("%d%d",&s,&t);    
        for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
         if(i!=j&&k!=j&&k!=i&&f[i][k]+f[k][j]<f[i][j])f[i][j]=f[i][k]+f[k][j]; 
        printf("%.2lf",f[s][t]);
        return 0;
    }
    floyd
    //Twenty
    #include<cstdio>
    #include<iostream> 
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn=500000;
    int n,m,s,t,first[maxn],next[maxn],wi[maxn],to[maxn],ecnt=0,dis[maxn],vis[maxn];
    int add(int x,int y,int w) {
        next[++ecnt]=first[x];first[x]=ecnt;to[ecnt]=y;wi[ecnt]=w;
        next[++ecnt]=first[y];first[y]=ecnt;to[ecnt]=x;wi[ecnt]=w;
    }
    int spfa() {
        queue<int>team;
        dis[s]=0;
        vis[s]=1;
        team.push(s);
        while(!team.empty()) {
            int x;
            x=team.front();
            team.pop();
            for(int i=first[x];i!=-1;i=next[i]) {
                if(wi[i]+dis[x]<dis[to[i]]) {
                  dis[to[i]]=wi[i]+dis[x];    
                  if(!vis[to[i]])
                  {vis[to[i]]=1;    
                  team.push(to[i]);}    
                }
            }
            vis[x]=0;
        }
        
    }
    
    int main()
    {
        memset(first,-1,sizeof(first));
        memset(vis,0,sizeof(vis));
        memset(dis,127,sizeof(dis));
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1;i<=m;i++) {
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w);
        }
        spfa();
        printf("%d",dis[t]);
        return 0;
    }
    SPFA模板

     

    2.最小生成树

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    using namespace std;
    int fa[10000],ans=0,k=0;
    struct edge {
        int u,v,w;
    }e[1000];
    bool cmp(const edge&a,const edge&b) {return a.w>b.w;}
    int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
    int main()
    {
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=m;i++)
          cin>>e[i].u>>e[i].v>>e[i].w;
        sort(e+1,e+1+m,cmp);
        for(int i=1;i<=n;i++)
        fa[i]=i;
        for(int i=1;i<=m;i++) {
            int u,v;
            u=e[i].u;v=e[i].v;
            u=find(u);v=find(v);
            if(u!=v) {
                ans+=e[i].w;
                fa[u]=v;
                k++;
                if(k==n-1)break;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    kruskal
    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int ans=0,n,a[150][150],vis[150],dis[150];
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        cin>>a[i][j];
        memset(dis,127,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis[1]=0;
        for(int i=1;i<=n;i++) {
            int k=0;
            for(int j=1;j<=n;j++)
            if(!vis[j]&&dis[j]<dis[k])
            k=j;
            vis[k]=1;
            for(int j=1;j<=n;j++)
             if(!vis[j]&&dis[j]>a[k][j])
               dis[j]=a[k][j];        
        }
        for(int i=1;i<=n;i++)
        ans+=dis[i];
        cout<<ans<<endl;
        return 0;
    }
    prim

     

    3.dfs_spfa判负环

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=200000+29;
    using namespace std;
    int flag,x,y,z,T,n,m,fir[maxn],nxt[maxn<<1],to[maxn<<1],val[maxn<<1],ecnt,vis[maxn],dis[maxn];
    void add(int u,int v,int w){
        nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
    }
    void dfs_spfa(int x){
        if(vis[x]) {flag=1;return;}
        vis[x]=1;
        for(int i=fir[x];i;i=nxt[i])
            if(dis[to[i]]>val[i]+dis[x]){
                dis[to[i]]=val[i]+dis[x];
                dfs_spfa(to[i]);
                if(flag) return;
            }
        vis[x]=0;
    }
    int main()
    {
       scanf("%d",&T);
       while(T--){
       flag=0;
       scanf("%d%d",&n,&m);
       for(int i=1;i<=m;i++){
           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++) dis[i]=vis[i]=0;
       for(int i=1;i<=n;i++)
        {dfs_spfa(i);
        if(flag) break;}
       if(flag) printf("YE5
    ");
       else printf("N0
    ");
       for(int i=1;i<=n;i++) fir[i]=0;
       for(int j=1;j<=ecnt;j++) nxt[j]=to[j]=0;
       ecnt=0;  
       }
       return 0;
    }
    dfs_spfa判负环

     

    4.LCA

    //Twenty
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=2*500000;
    int n,n2,n3,a,b;
    int first[maxn],next[maxn],to[maxn],vis[maxn],firstarrive[maxn],R[maxn],cur[maxn];
    int dp[maxn][20]; 
    int ecnt=0;
    int add(int u,int v) {
        next[++ecnt]=first[u];first[u]=ecnt;to[ecnt]=v;
        next[++ecnt]=first[v];first[v]=ecnt;to[ecnt]=u;    
    }
    int cnt=0;
    void dfs(int node,int dep) {
        vis[node]=1;
        cur[++cnt]=node;
        R[cnt]=dep;
        firstarrive[node]=cnt;
        for(int i=first[node];i!=-1;i=next[i]) {
            if(!vis[to[i]]) {
                dfs(to[i],dep+1);
                cur[++cnt]=node;
                R[cnt]=dep;
            }
            
        }    
    }
    
    void ST(int n) {
        for(int i=1;i<=n;i++)
        dp[i][0]=i;
        for(int j=1;(1<<j)<=n;j++)
        for(int i=1;(i+(1<<j)-1)<=n;i++) {
            int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1];
            dp[i][j]=R[a]<R[b]?a:b;
        } 
    }
    int RMQ(int l,int r) {
        int k=0;
        while(l+(1<<(k+1))-1<=r) {
            k++;
        }
        int a=dp[l][k],b=dp[r-(1<<k)+1][k];
        return R[a]<R[b]?a:b;
    }
    int LCA(int a,int b) {
        a=firstarrive[a];
        b=firstarrive[b];
        if(a>b)swap(a,b);
        return cur[RMQ(a,b)];
    }
    int main()
    {
        memset(first,-1,sizeof(first));
        scanf("%d%d%d",&n,&n2,&n3);
        for(int i=1;i<n;i++) {
        scanf("%d%d",&a,&b);     
        add(a,b);
        }
        dfs(n3,1);
        ST(2*n);
        while(n2--) {
            scanf("%d%d",&a,&b);
            printf("%d
    ",LCA(a,b));
        }
        return 0;
    }
    RMQ求LCA
    //Twenty
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=5000;
    int n,n2,n3,a,b;
    int first[maxn],next[maxn],to[maxn],fa[maxn],vis[maxn];
    int firstcheck[maxn],nextcheck[maxn],tocheck[maxn];
    int ans[maxn][maxn],check[maxn][3];
    int dp[maxn][20]; 
    int ecnt=0;
    int add(int u,int v) {
        next[++ecnt]=first[u];first[u]=ecnt;to[ecnt]=v;
        next[++ecnt]=first[v];first[v]=ecnt;to[ecnt]=u;    
    }
    int addcheck(int u,int v) {
        nextcheck[++ecnt]=firstcheck[u];firstcheck[u]=ecnt;tocheck[ecnt]=v;
        nextcheck[++ecnt]=first[v];firstcheck[v]=ecnt;tocheck[ecnt]=u;    
    }
    int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
    int dfs(int node,int far) {
        vis[node]=1;
        for(int i=first[node];i!=0;i=next[i]) {
            if(!vis[to[i]]) {
                dfs(to[i],node);
            }
        }
        fa[node]=far;
        for(int i=firstcheck[node];i!=0;i=next[i]) {
            if(!vis[tocheck[i]])
            continue;
            else ans[tocheck[i]][node]=ans[node][tocheck[i]]=find(tocheck[i]);
        }    
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&n2,&n3);
        for(int i=1;i<n;i++) {
        scanf("%d%d",&a,&b);     
        add(a,b);
        }
        for(int i=1;i<=n;i++)
        fa[i]=i;
        for(int i=1;i<=n2;i++) {
            cin>>a>>b; 
            check[i][1]=a;
            check[i][2]=b;
            addcheck(a,b);
        }
        dfs(1,1);
        for(int i=1;i<=n2;i++)
            printf("%d
    ",ans[check[i][1]][check[i][2]]); 
        return 0;
    }
    tarjan求LCA
    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=500005;
    using namespace std;
    int n,q,s,x,y,fir[maxn],next[maxn*2],to[maxn*2],fa[maxn][20],vis[maxn],R[maxn];
    int ecnt;
    inline int add(int u,int v){
        next[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
        next[++ecnt]=fir[v];fir[v]=ecnt;to[ecnt]=u;
    }
    int dfs(int x,int f) {
        
        vis[x]=1;
        R[x]=R[f]+1;
        fa[x][0]=f;
        for(int i=fir[x];i!=0;i=next[i]) {
            if(!vis[to[i]]) {
                dfs(to[i],x);
            }
        } 
    }
    void init() {
        for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i<=n;i++)
        {
            if(fa[i][j-1]!=-1)
            fa[i][j]=fa[fa[i][j-1]][j-1];
        }
    }
    int LCA(int a,int b){
        if(R[a]<R[b]) swap(a,b);
        int i;
        for(i=0;(1<<i)<=R[a];i++);
        i--;
        for(int j=i;j>=0;j--) {
            if(R[a]-(1<<j)>=R[b])
            a=fa[a][j];
        }
        if(a==b) return a;
        for(int j=i;j>=0;j--) {
            if(fa[a][j]!=-1&&fa[a][j]!=fa[b][j]) {
                 a=fa[a][j];
                 b=fa[b][j];
             }
        }    
        return fa[a][0];
    }
    int main()
    {
       memset(fa,-1,sizeof(fa));
       scanf("%d%d%d",&n,&q,&s);
       for(int i=1;i<n;i++) {
            scanf("%d%d",&x,&y);
            add(x,y);
       }
       dfs(s,s);
       init();
       while(q--) {
           scanf("%d%d",&x,&y);
           printf("%d
    ",LCA(x,y));
       }
       return 0;
    }
    倍增求LCA

     

    5.tarjan

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<stack>
    const int maxn=(1e5+299)*2;
    using namespace std;
    int ecnt,v[maxn],fir[maxn],nxt[maxn],to[maxn],dp[maxn],dfn[maxn],low[maxn];
    int clock,nn,xn,m,sccno[maxn],ans;
    void add(int x,int y){
        nxt[++ecnt]=fir[x]; fir[x]=ecnt; to[ecnt]=y;
    }
    stack<int>sta;
    void tarjan(int x){
        dfn[x]=low[x]=++clock;
        sta.push(x);
        for(int i=fir[x];i;i=nxt[i]){
            if(!dfn[to[i]]){
                tarjan(to[i]);
                low[x]=min(low[x],low[to[i]]);
            }
            else if(!sccno[to[i]])
                low[x]=min(low[x],dfn[to[i]]);
        }
        if(dfn[x]==low[x])
        {
            xn++;
            for(;;){
               int u=sta.top();
               sta.pop();
               sccno[u]=xn;
               v[xn]+=v[u];
               if(u==x) break;
            }
        }
    }
    void Dp(int x){
        if(dp[x]) return;
        int now=0;
        for(int i=fir[x];i;i=nxt[i]){
            Dp(to[i]);
            now=max(now,dp[to[i]]);
        }
        dp[x]=v[x]+now;
    }
    int main()
    {
        scanf("%d%d",&nn,&m); 
        xn=nn;
        for(int i=1;i<=nn;i++) scanf("%d",&v[i]);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        for(int i=1;i<=nn;i++)
            if(!dfn[i]) 
            tarjan(i);    
        for(int i=1;i<=nn;i++)
         for(int j=fir[i];j;j=nxt[j]){
            int u=i,v=to[j];
            if(sccno[u]!=sccno[v])
              add(sccno[u],sccno[v]);
         }
        for(int i=nn+1;i<=xn;i++){
            Dp(i);
            ans=max(ans,dp[i]);
        }
        printf("%d
    ",ans);
        return 0;
    }
    tarjan强连通分量 缩点
    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=(100000+299)*2; 
    using namespace std;
    int clock,ecnt,n,m,fir[maxn],nxt[maxn],to[maxn],dfn[maxn],low[maxn];
    int cut[maxn],ans; 
    void add(int x,int y){
        nxt[++ecnt]=fir[x]; fir[x]=ecnt; to[ecnt]=y;
        nxt[++ecnt]=fir[y]; fir[y]=ecnt; to[ecnt]=x;
    }
    void tarjan(int x,int rt){
        int rc=0;
        dfn[x]=low[x]=++clock;
        for(int i=fir[x];i;i=nxt[i]){
            if(!dfn[to[i]]){
                tarjan(to[i],rt);
                low[x]=min(low[x],low[to[i]]);
                if(low[to[i]]>=dfn[x]&&x!=rt) cut[x]=1;
                if(x==rt) rc++;
            }
            else low[x]=min(low[x],dfn[to[i]]);
        }
        if(x==rt&&rc>=2) cut[x]=1; 
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
             int x,y;
             scanf("%d%d",&x,&y);
             add(x,y);
        }
        for(int i=1;i<=n;i++)
          if(!dfn[i]) tarjan(i,i);
        for(int i=1;i<=n;i++)
          if(cut[i]) ans++;
        printf("%d
    ",ans);
        for(int i=1;i<=n;i++)
         if(cut[i]) printf("%d ",i);
        return 0;
    }
    tarjan 割点
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    typedef long long LL;
    using namespace std;
    const int maxn=10000+299;
    const int maxm=100000*2+299;
    int T,n,m,x,y,fir[maxn],nxt[maxm],to[maxm],fa[maxn],cc,cut[maxm],dfn[maxn],id[maxm],low[maxn],dfs_clock,ecnt;
    void add(int x,int y,int tot) { 
        nxt[++ecnt]=fir[x]; fir[x]=ecnt; to[ecnt]=y; id[ecnt]=tot;
        nxt[++ecnt]=fir[y]; fir[y]=ecnt; to[ecnt]=x; id[ecnt]=tot;
    }
    void clear() {
        memset(fir,0,sizeof(fir));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(cut,0,sizeof(cut));
        memset(fa,0,sizeof(fa)); ecnt=0;
        dfs_clock=0;
    }
    void tarjan(int x) {
        dfn[x]=low[x]=++dfs_clock;
        for(int i=fir[x];i;i=nxt[i]) {
            if(!dfn[to[i]]) {
                fa[to[i]]=i;
                tarjan(to[i]);
                low[x]=min(low[x],low[to[i]]);
            }
            else if(id[fa[x]]!=id[i]) low[x]=min(low[x],dfn[to[i]]);
        }
        if(fa[x]&&dfn[x]==low[x]) {
            cc++; 
            cut[id[fa[x]]]=1;
        }
    }
    int main()
    {
        scanf("%d",&T);
        while(T) {
            clear();
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++) {
                scanf("%d%d",&x,&y);
                add(x,y,i);    
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i]) tarjan(i);
            printf("%d
    ",cc);
            for(int i=1;i<=m;i++) 
                if(cut[i]) { cc--; if(cc) printf("%d ",i); else printf("%d
    ",i);}
            --T;
            if(T) printf("
    ");
        }
        return 0;
    }
    tarjan 求桥

     

    6.拓扑排序

    //Twenty
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxn=50000;
    const int maxm=2.5*maxn;
    int n,m,a,b,ans;
    int first[maxn],next[maxm],to[maxm],integ[maxn];
    int ecnt=0;
    int add(int u,int v){
        next[++ecnt]=first[u];first[u]=ecnt;to[ecnt]=v;}
    int toposort(){
        queue<int>team;
        for(int i=1;i<=n;i++){if(integ[i]==0) team.push(i);}
        while(!team.empty() ) {  
           int x=team.front(); team.pop();
           for(int i=first[x];i!=0;i=next[i]){
            integ[to[i]]--;
            if(integ[to[i]]==0)team.push(to[i]);    
          }
        }   
        for(int i=1;i<=n;i++)
          if(integ[i])ans++;
    }
    
    int main()
    {
        scanf("%d",&n);
        scanf("%d",&m);
        for(int i=1;i<=m;i++) {
            scanf("%d%d",&a,&b);
            integ[b]++;
            add(a,b);
        }
        toposort();
        if(ans==0)printf("o(∩_∩)o");
        else printf("T_T
    %d",ans);
        return 0;
    }
    奇怪的梦境

     

    7.匈牙利算法

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    const int maxn=2005;
    int n,m,u,v,e,ecnt,ans,fir[maxn],next[maxn*maxn],to[maxn*maxn],f[maxn],pre[maxn];
    using namespace std;
    void add(int u,int v){
        next[++ecnt]=fir[u];to[ecnt]=v;fir[u]=ecnt;
    }
    int find(int x){
        for(int i=fir[x];i;i=next[i])
          if(!f[to[i]]){
             f[to[i]]=1;
             if(!pre[to[i]]||find(pre[to[i]])){
                 pre[to[i]]=x;
                 return 1;
             }
          }
        return 0;
    }
    int main()
    {
       scanf("%d%d%d",&n,&m,&e);
       for(int i=1;i<=e;i++){
          scanf("%d%d",&u,&v);
          if(u<=m&&v<=m) add(u,v+1000);
       } 
       for(int i=1;i<=n;i++){
            memset(f,0,sizeof(f));
         ans+=find(i);
       }
       printf("%d
    ",ans);
       return 0;
    }
    匈牙利

     

  • 相关阅读:
    html5语法
    Addthis使用
    css font-weight原理
    css3 background
    jquery对标签属性操作
    给textarea添加背景图
    label的for属性
    css3 text-shadow
    z-index堆叠规则
    css3 @font-face
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7475189.html
Copyright © 2011-2022 走看看