【算法提高——第三讲(一)】图论(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;
}

相关文章
|
4月前
|
机器学习/深度学习 安全 算法
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
|
4月前
|
算法 测试技术 C++
【动态规划】【图论】【C++算法】1575统计所有可行路径
【动态规划】【图论】【C++算法】1575统计所有可行路径
|
11月前
|
存储 算法 索引
数据结构与算法之图论及其相关算法
图的基本介绍 线性表局限于一个直接前驱和一个直接后继的关系,树也只能有一个直接前驱也就是父节点,当我们需要表示多对多的关系时, 这里我们就用到了图。 图是一种数据结构,其中结点可以具有零个或多个相邻元素。两个结点之间的连接称为边。 结点也可以称为顶点。如图: 简单来说,图就是由顶点的有穷非空集合和顶点之间的边组成的集合。通常表示为:G(V,E),其中,G 表示一个图,V 表示顶点的集合,E 表示边的集合。 然后我们说说图中的一些常见概念: 节点(Vertex):图中的基本元素,用于表示某个实体。 边(Edge):连接两个节点的线段,用于表示节点之间的关系。 度(Degree):
46 0
|
4月前
|
算法 测试技术 C++
【动态规划】【图论】【C++算法】1928规定时间内到达终点的最小花费
【动态规划】【图论】【C++算法】1928规定时间内到达终点的最小花费
|
3月前
|
算法 数据挖掘 定位技术
算法必备数学基础:图论方法由浅入深实践与应用
算法必备数学基础:图论方法由浅入深实践与应用
|
10月前
|
算法 存储 内存技术
【AcWing算法基础课】第三章 搜索与图论(2)
特点:尽可能先向纵深方向搜索。使用stack实现。所需空间O(h)(h为深度)。不具有“最短性”。
69 0
【AcWing算法基础课】第三章 搜索与图论(2)
|
4月前
|
算法 C++
一题带你写出图论算法模板!!!
一题带你写出图论算法模板!!!
|
4月前
|
算法 搜索推荐 Python
Python高级数据结构——图论算法(Graph Algorithms)
Python高级数据结构——图论算法(Graph Algorithms)
140 0
|
4月前
|
算法 C++ NoSQL
|
4月前
|
存储 算法 定位技术
图论算法dijkstra dfs bfs以及动态规划
图论算法dijkstra dfs bfs以及动态规划
67 0