【算法提高——第三讲(一)】图论(2)

简介: 【算法提高——第三讲(一)】图论(2)

3.4 Floyd算法

3.4.1 1125. 牛的旅行

image.png

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=160;
const double INF=1e20;
char g[N][N];
PII q[N];
int n;
double d[N][N],maxd[N];
double get_dist(PII a,PII b)
{
    double x=a.first-b.first,y=a.second-b.second;
    return sqrt(x*x+y*y);
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>q[i].first>>q[i].second;
    }
    for(int i=0;i<n;i++)
    {
        cin>>g[i];
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(i!=j)
            {
                if(g[i][j]=='1') d[i][j]=get_dist(q[i],q[j]);
                else d[i][j]=INF;
            }
        }
    }
    for(int k=0;k<n;k++)
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(d[i][j]<INF)
            {
                maxd[i]=max(maxd[i],d[i][j]);
            }
        }
    }
    double res1=0;
    for(int i=0;i<n;i++)
        res1=max(res1,maxd[i]);
    double res2=INF;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(d[i][j]>=INF)
            {
                double dist=get_dist(q[i],q[j]);
                res2=min(res2,maxd[i]+dist+maxd[j]);
            }
        }
    }
    printf("%.6f",max(res1,res2));
    return 0;
}

3.4.2 343. 排序

image.png

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=30;
int n,m;
bool g[N][N],d[N][N];
bool st[N];
void floyd()
{
    memcpy(d,g,sizeof d);
    for(int k=0;k<n;k++)
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                d[i][j]|=d[i][k]&&d[k][j];
            }
        }
    }
}
int check()
{
    for(int i=0;i<n;i++)
    {
        if(d[i][i])
            return 2;
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<i;j++)
        {
            if(!d[i][j]&&!d[j][i])
            {
                return 0;
            }
        }
    }
    return 1;
}
char get_min()
{
    for(int i=0;i<n;i++)
    {
        if(!st[i])
        {
            bool flag=true;
            for(int j=0;j<n;j++)
            {
                if(!st[j]&&d[j][i])
                {
                    flag=false;
                    break;
                }
            }
            if(flag)
            {
                st[i]=true;
                return i+'A';
            }
        }
    }
}
int main()
{
    while(true)
    {
        cin>>n>>m;
        if(n==0&&m==0)
            break;
        memset(g,0,sizeof g);
        //注意type的意义和讲的时候不一样
        int type=0,t;
        for(int i=1;i<=m;i++)
        {
            string str;
            cin>>str;
            int a=str[0]-'A',b=str[2]-'A';
            if(!type)
            {
                g[a][b]=1;
                floyd();
                type=check();
                if(type) t=i;
            }
        }
        if(!type)
            cout<<"Sorted sequence cannot be determined."<<endl;
        else if(type==2)
            cout<<"Inconsistency found after "<<t<<" relations."<<endl;
        else
        {
            memset(st,0,sizeof st);
            cout<<"Sorted sequence determined after "<<t<<" relations: ";
            for(int i=0;i<n;i++)
                cout<<get_min();
            cout<<"."<<endl;
        }
    }
    return 0;
}

3.4.3 344. 观光之旅

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=110,INF=0x3f3f3f3f;
int n,m;
int d[N][N],g[N][N];
int pos[N][N];
int path[N],cnt;
void get_path(int i,int j)
{
    if(pos[i][j]==0) return;
    int k=pos[i][j];
    get_path(i,k);
    path[cnt++]=k;
    get_path(k,j);
}
int main()
{
    cin>>n>>m;
    memset(g,0x3f,sizeof g);
    for(int i=1;i<=n;i++) g[i][i]=0;
    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b]=g[b][a]=min(g[a][b],c);
    }
    int res=INF;
    memcpy(d,g,sizeof d);
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<k;i++)
        {
            //for(int j=1;j<i;j++)
            for(int j=i+1;j<k;j++)
            {
                if((long long)d[i][j]+g[i][k]+g[k][j]<res)
                {
                    res=d[i][j]+g[i][k]+g[k][j];
                    cnt=0;
                    path[cnt++]=k;
                    path[cnt++]=i;
                    get_path(i,j);
                    path[cnt++]=j;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(d[i][j]>d[i][k]+d[k][j])
                {
                    d[i][j]=d[i][k]+d[k][j];
                    pos[i][j]=k;
                }
            }
        }
    }
    if(res==INF) cout<<"No solution.";
    for(int i=0;i<cnt;i++)
    {
        cout<<path[i]<<" ";
    }
    return 0;
}

3.4.4 345. 牛站

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=210,M=2010,INF=0x3f3f3f3f;
int k,n,m,S,E;
int g[N][N];
int res[N][N];
void mul(int c[][N],int a[][N],int b[][N])
{
    static int temp[N][N];
    memset(temp,0x3f,sizeof temp);
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                temp[i][j]=min(temp[i][j],a[i][k]+b[k][j]);
            }
        }
    }
    memcpy(c,temp,sizeof temp);
}
void qmi()
{
    memset(res,0x3f,sizeof res);
    for(int i=1;i<=n;i++) res[i][i]=0;
    while(k)
    {
        if(k&1) mul(res,res,g);
        mul(g,g,g);
        k>>=1;
    }
}
int main()
{
    cin>>k>>m>>S>>E;
    memset(g,0x3f,sizeof g);
    map<int,int> mp;
    if(mp.count(S)==0) mp[S]=++n;
    if(mp.count(E)==0) mp[E]=++n;
    S=mp[S],E=mp[E];
    while(m--)
    {
        int a,b,c;
        cin>>c>>a>>b;
        if(mp.count(a)==0) mp[a]=++n;
        if(mp.count(b)==0) mp[b]=++n;
        a=mp[a],b=mp[b];
        g[a][b]=g[b][a]=min(g[a][b],c);
    }
    qmi();
    cout<<res[S][E]<<endl;
    return 0;
}

3.5 最小生成树

3.5.1 1140. 最短网络

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=110,INF=0x3f3f3f3f;
int n;
int g[N][N];
int dis[N];
bool st[N];
int prim()
{
    memset(dis,0x3f,sizeof dis);
    int res=0;
    for(int i=0;i<n;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
        {
            if(!st[j]&&(t==-1||dis[t]>dis[j]))
                t=j;
        }
        if(i&&dis[t]==INF)
            return INF;
        if(i) res+=dis[t];
        st[t]=true;
        for(int j=1;j<=n;j++)
            dis[j]=min(dis[j],g[t][j]);
    }
    return res;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            cin>>g[i][j];
    cout<<prim();
    return 0;
}

3.5.2 1141. 局域网

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=110,INF=0x3f3f3f3f;
int n,m,sum;
int p[N];
struct Edge{
    int a,b,w;
    bool operator < (const Edge &W)const
    {
        return w<W.w;
    }
}edges[N];
int findP(int x)
{
    if(p[x]!=x) p[x]=findP(p[x]);
    return p[x];
}
int kruskal()
{
    sort(edges,edges+m);
    for(int i=1;i<=n;i++) p[i]=i;
    int res=0;
    for(int i=0;i<m;i++)
    {
        int a=edges[i].a,b=edges[i].b,w=edges[i].w;
        a=findP(a),b=findP(b);
        if(a!=b)
        {
            p[a]=b;
            res+=w;
        }
    }
    return res;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        edges[i].a=a,edges[i].b=b,edges[i].w=c;
        sum+=c;
    }
    cout<<sum-kruskal()<<endl;
    return 0;
}

3.5.3 1142. 繁忙的都市

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=310,M=80010;
int n,m;
int p[N];
struct Edge{
    int a,b,w;
}edges[M];
bool cmp(Edge a,Edge b)
{
    return a.w<b.w;
}
int findP(int x)
{
    if(p[x]!=x) return p[x]=findP(p[x]);
    return p[x];
}
int kruskal()
{
    sort(edges,edges+m,cmp);
    for(int i=1;i<=n;i++) p[i]=i;
    int res=-1;
    for(int i=0;i<m;i++)
    {
        int a=edges[i].a,b=edges[i].b,w=edges[i].w;
        a=findP(a),b=findP(b);
        if(a!=b)
        {
            p[a]=b;
            res=max(res,w);
        }
    }
    return res;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
        cin>>edges[i].a>>edges[i].b>>edges[i].w;
    cout<<n-1<<" "<<kruskal()<<endl;
    return 0;
}

3.5.4 1143. 联络员

image.png


代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2010,M=10010;
int n,m;
int p[N];
struct Edge{
    int a,b,w,type;
}edges[M];
bool cmp(Edge a,Edge b)
{
    if(a.type!=b.type)
        return a.type<b.type;
    else
        return a.w<b.w;
}
int findP(int x)
{
    if(p[x]!=x) return p[x]=findP(p[x]);
    return p[x];
}
int kruskal()
{
    sort(edges,edges+m,cmp);
    for(int i=1;i<=n;i++) p[i]=i;
    int res=0;
    for(int i=0;i<m;i++)
    {
        int type=edges[i].type,a=edges[i].a,b=edges[i].b,w=edges[i].w;
        a=findP(a),b=findP(b);
        if(a!=b)
        {
            p[a]=b;
            res+=w;
        }
        else if(type==1)
        {
            res+=w;
        }
    }
    return res;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
        cin>>edges[i].type>>edges[i].a>>edges[i].b>>edges[i].w;
    cout<<kruskal();
    return 0;
}

3.5.5 1144. 连接格点

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=1010,M=2000010;
int n,m;
int p[M];
int cnt;
int mp[M];
int dx[2]={0,1},dy[2]={1,0};
struct Edge{
    int a,b,w;
}edges[M];
bool cmp(Edge a,Edge b)
{
    return a.w<b.w;
}
int findP(int x)
{
    if(p[x]!=x) p[x]=findP(p[x]);
    return p[x];
}
int kruskal()
{
    sort(edges,edges+cnt,cmp);
    int res=0;
    for(int i=0;i<cnt;i++)
    {
        int a=edges[i].a,b=edges[i].b,w=edges[i].w;
        a=findP(a),b=findP(b);
        if(a!=b)
        {
            p[a]=b;
            res+=w;
        }
    }
    return res;
}
int main()
{
    cin>>n>>m;
    int x1,y1,x2,y2;
    for(int i=1;i<=N*N;i++) p[i]=i;
    while(cin>>x1>>y1>>x2>>y2)
    {
        int a=(x1-1)*n+y1,b=(x2-1)*n+y2;
        mp[a]=b;
        a=findP(a),b=findP(b);
        if(a!=b)
            p[a]=b;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            for(int k=0;k<2;k++)
            {
                int x=i+dx[k],y=j+dy[k];
                if(x<=0||x>n||y<=0||y>m)
                    continue;
                int a=(i-1)*n+j,b=(x-1)*n+y;
                if(mp[a]==b)
                    continue;
                edges[cnt].a=a,edges[cnt].b=b;
                if(i==x)
                    edges[cnt].w=2;
                else
                    edges[cnt].w=1;
                cnt++;
            }
        }
    }
    cout<<kruskal();
    return 0;
}

相关文章
|
30天前
|
存储 算法 数据管理
【C/C++ 基础算法】 C/C++ 位图算法的使用
【C/C++ 基础算法】 C/C++ 位图算法的使用
35 0
|
29天前
|
存储 机器学习/深度学习 算法
图论基础:从数学原理到C/C++实现
图论基础:从数学原理到C/C++实现
73 0
|
算法 Python
算法理论——回溯算法及剪枝优化
回溯法也可以叫做回溯搜索法,它是一种搜索的方式。
222 0
算法理论——回溯算法及剪枝优化
|
10月前
|
算法
图论
图论
52 0
|
10月前
|
算法 搜索推荐
从图到算法【图论】
柯尼斯堡七桥问题是图论中的著名问题。
60 0
|
12月前
|
算法 关系型数据库 MySQL
数据结构与算法——深度寻路算法
📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段,因为最近参加新星计划算法赛道(白佬),所以加快了脚步,果然急迫感会增加动力>——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的 📖作者主页:king&南星 📖专栏链接:数据结构 🎉欢迎各位→点赞👏 + 收藏💞 + 留言🔔​ 💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🐾 ———————————————— 版权声明:本文为CSDN博主「热爱编程的小K」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
|
存储 算法 C++
秒懂算法 | 图论
图论是一个“巨大”的专题,有大量的知识点,有众多广为人知的问题,有复杂的应用场景。 图论算法常常建立在复杂的数据结构之上。本文讲解了基础的图论考点,帮助大家了解图论专题
169 0
|
算法 定位技术
图论的灵魂——带你走进迪杰斯特拉算法的世界
图论的灵魂——带你走进迪杰斯特拉算法的世界
图论的灵魂——带你走进迪杰斯特拉算法的世界
【算法提高——第三讲(二)】图论(1)
【算法提高——第三讲(二)】图论(1)
【算法提高——第三讲(二)】图论(1)
【算法提高——第三讲(二)】图论(2)
【算法提高——第三讲(二)】图论(2)
【算法提高——第三讲(二)】图论(2)