【算法提高——第三讲(二)】图论(1)

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


3.7 负环

3.7.1 904. 虫洞

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=510,M=6010;
int F,n,m,W;
int h[N],e[M],w[M],ne[M],idx;
int dis[N];
bool st[N];
int cnt[N];
void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool spfa()
{
    memset(cnt,0,sizeof cnt);
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    queue<int> q;
    for(int i=1;i<=n;i++)
    {
        q.push(i);
        st[i]=true;
    }
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]>dis[t]+w[i])
            {
                dis[j]=dis[t]+w[i];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=n) return true;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    return false;
}
int main()
{
    ios::sync_with_stdio(0);
    cin>>F;
    while(F--)
    {
        memset(h,-1,sizeof h);
        idx=0;
        cin>>n>>m>>W;
        for(int i=0;i<m;i++)
        {
            int a,b,c;
            cin>>a>>b>>c;
            add(a,b,c),add(b,a,c);
        }
        for(int i=0;i<W;i++)
        {
            int a,b,c;
            cin>>a>>b>>c;
            add(a,b,-c);
        }
        if(spfa()) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

3.7.2 361. 观光奶牛

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=1010,M=5010;
int n,m;
int wf[N];
double dis[N];
bool st[N];
int cnt[N];
int h[N],e[M],w[M],ne[M],idx;
void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool check(double mid)
{
    memset(dis,0,sizeof dis);
    memset(st,0,sizeof st);
    memset(cnt,0,sizeof cnt);
    queue<int> q;
    for(int i=1;i<=n;i++)
    {
        q.push(i);
        st[i]=true;
    }
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]<dis[t]+wf[t]-mid*w[i])
            {
                dis[j]=dis[t]+wf[t]-mid*w[i];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=n) return true;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    return false;
}
int main()
{
    memset(h,-1,sizeof h);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>wf[i];
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    double l=0,r=1010;
    while(r-l>1e-4)
    {
        double mid=(l+r)/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    printf("%.2f",r);
    return 0;
}

3.7.3 1165. 单词环

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=700,M=100010;
int n;
double dis[N];
bool st[N];
int cnt[N];
int h[N],e[M],w[M],ne[M],idx;
void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool check(double mid)
{
    memset(dis,0,sizeof dis);
    memset(st,0,sizeof st);
    memset(cnt,0,sizeof cnt);
    queue<int> q;
    for(int i=0;i<n;i++)
    {
        q.push(i);
        st[i]=true;
    }
    int sum=0;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]<dis[t]+w[i]-mid)
            {
                dis[j]=dis[t]+w[i]-mid;
                cnt[j]=cnt[t]+1;
                sum++;
                if(cnt[j]>=n) return true;
                if(sum>4*n) return true;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    return false;
}
int main()
{
    while(true)
    {
        memset(h,-1,sizeof h);
        cin>>n;
        if(n==0)
            break;
        for(int i=1;i<=n;i++)
        {
            string str;
            cin>>str;
            int len=str.length();
            if(len<2) continue;
            string left=str.substr(0,2),right=str.substr(len-2);
            int a=(left[0]-'a')*26+left[1]-'a',b=(right[0]-'a')*26+right[1]-'a';
            add(a,b,len);
        }
        n=26*26;
        if(check(0))
        {
            double l=0,r=1010;
            while(r-l>1e-4)
            {
                double mid=(l+r)/2;
                if(check(mid)) l=mid;
                else r=mid;
            }
            printf("%.2f\n",r);
        }
        else
            cout<<"No solution"<<endl;
    }
    return 0;
}

3.8 差分约束

3.8.1 1169. 糖果

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100010,M=300010;
int n,m;
LL dis[N];
int cnt[N];
bool st[N];
int h[N],e[M],w[M],ne[M],idx;
void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool spfa()
{
    memset(dis,-0x3f,sizeof dis);
    dis[0]=0;
    stack<int> q;
    q.push(0);
    st[0]=true;
    int sum=0;
    while(q.size())
    {
        int t=q.top();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]<dis[t]+w[i])
            {
                dis[j]=dis[t]+w[i];
                cnt[j]=cnt[t]+1;
                sum++;
                if(sum>10*n) return false;
                if(cnt[j]>=n+1) return false;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    return true;
}
int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof h);
    for(int i=0;i<m;i++)
    {
        int x,a,b;
        cin>>x>>a>>b;
        if(x==1) add(a,b,0),add(b,a,0);
        else if(x==2) add(a,b,1);
        else if(x==3) add(b,a,0);
        else if(x==4) add(b,a,1);
        else add(a,b,0);
    }
    for(int i=1;i<=n;i++) add(0,i,1);
    if(!spfa())
    {
        cout<<-1<<endl;
    }
    else
    {
        LL res=0;
        for(int i=1;i<=n;i++)
            res+=dis[i];
        cout<<res;
    }
    return 0;
}

3.8.2 362. 区间

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=50010,M=150010;
int n;
int dis[N];
bool st[N];
int h[N],e[M],w[M],ne[M],idx;
void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void spfa()
{
    memset(dis,-0x3f,sizeof dis);
    dis[0]=0;
    queue<int> q;
    q.push(0);
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]<dis[t]+w[i])
            {
                dis[j]=dis[t]+w[i];
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
}
int main()
{
    memset(h,-1,sizeof h);
    cin>>n;
    for(int i=1;i<=50001;i++)
    {
        add(i-1,i,0);
        add(i,i-1,-1);
    }
    for(int i=0;i<n;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        a++,b++;
        add(a-1,b,c);
    }
    spfa();
    cout<<dis[50001];
    return 0;
}

3.8.3 1170. 排队布局

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=1010,M=30010;
int n,L,D;
int dis[N],cnt[N];
bool st[N];
int h[N],e[M],w[M],ne[M],idx;
void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool spfa(int x)
{
    memset(dis,0x3f,sizeof dis);
    memset(st,0,sizeof st);
    memset(cnt,0,sizeof cnt);
    queue<int> q;
    for(int i=1;i<=x;i++)
    {
        q.push(i);
        dis[i]=0;
        st[i]=true;
    }
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]>dis[t]+w[i])
            {
                dis[j]=dis[t]+w[i];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=n) return true;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    return false;
}
int main()
{
    memset(h,-1,sizeof h);
    cin>>n>>L>>D;
    for(int i=1;i<n;i++)
        add(i+1,i,0);
    for(int i=0;i<L;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        int _min=min(a,b),_max=max(a,b);
        add(_min,_max,c);
    }
    for(int i=0;i<D;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        int _min=min(a,b),_max=max(a,b);
        add(_max,_min,-c);
    }
    if(spfa(n))
        cout<<-1<<endl;
    else
    {
        spfa(1);
        if(dis[n]==0x3f3f3f3f) cout<<-2<<endl;
        else cout<<dis[n]<<endl;
    }
    return 0;
}

3.8.4 393. 雇佣收银员

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=30,M=100;
int n;
int dis[N],cnt[N];
int r[N],num[N];
bool st[N];
int h[N],e[M],w[M],ne[M],idx;
void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void build(int c)
{
    memset(h,-1,sizeof h);
    idx=0;
    for(int i=1;i<=24;i++)
    {
        add(i-1,i,0);
        add(i,i-1,-num[i]);
    }
    for(int i=1;i<=7;i++) add(i+16,i,r[i]-c);
    for(int i=8;i<=24;i++) add(i-8,i,r[i]);
    add(0,24,c),add(24,0,-c);
}
bool spfa(int c)
{
    build(c);
    memset(dis,-0x3f,sizeof dis);
    memset(cnt,0,sizeof cnt);
    memset(st,0,sizeof st);
    queue<int> q;
    q.push(0);
    dis[0]=0;
    st[0]=true;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]<dis[t]+w[i])
            {
                dis[j]=dis[t]+w[i];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=25) return false;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    return true;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        for(int i=1;i<=24;i++) cin>>r[i];
        cin>>n;
        memset(num,0,sizeof num);
        for(int i=0;i<n;i++)
        {
            int t;
            cin>>t;
            num[t+1]++;
        }
        bool success=false;
        for(int i=0;i<=1000;i++)
        {
            if(spfa(i))
            {
                cout<<i<<endl;
                success=true;
                break;
            }
        }
        if(!success)
            cout<<"No Solution"<<endl;
    }
    return 0;
}

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