L. Spicy Restaurant

题意:

n个火锅店,辣度分别是w[i],有q个人,每个人能忍受的最大辣度是g,有m条边 连接火锅店。求每个人能够去的火锅店最短距离。

思路:

由于w<=100,则所以直接枚举一个权值k k,把所有w[i] = k的点作为源点做一次多源bfs 那么可以预处理dis[i][j]表示j点距离最近的辣味i多远

然后顺着更新一遍dis[i][j]=min(dis[i][j],dis[i-1][j]);

代码:

#include<bits/stdc++.h>
using namespace std;
#define  N 200005
int n,m,q,inf,dis[105][N],w[N];
vector<int>ve[N];
void bfs(int c){
    queue<int>q;
    for (int i = 1; i <=n ; ++i) {
        if(w[i]==c)q.push(i),dis[c][i]=0;
    }
    while (!q.empty()){
        int u=q.front();
        q.pop();
        for (int i = 0; i < ve[u].size(); ++i) {
            if(dis[c][ve[u][i]]!=inf)continue;
            q.push(ve[u][i]);
            dis[c][ve[u][i]]=dis[c][u]+1;
        }
    }
}
int main(){
    memset(dis,0x3f,sizeof dis);
    inf=dis[0][0];
    cin>>n>>m>>q;
    for (int i = 1; i <=n ; ++i) {
        cin>>w[i];
    }
    for (int i = 0; i < m; ++i) {
        int a,b;
        cin>>a>>b;
        ve[a].push_back(b),ve[b].push_back(a);
    }
    for (int i = 100; i >=1 ; --i)bfs(i);
    for (int i = 1; i <=n ; ++i) {
        for (int j = 1; j <=100 ; ++j) {
            dis[j][i]=min(dis[j][i],dis[j-1][i]);
        }
    }
    while (q--){
        int a,b;
        cin>>b>>a;
        if(dis[a][b]==inf)
            cout<<"-1"<<endl;
        else
            cout<<dis[a][b]<<endl;
    }

}

2.E.


题意:

给一个n个节点的图,以及m条边,问需要加多少条边能dfs从1到n

思路:

  • 题目中是按照dfs顺序给出编号,所以从1结点开始,第二个点必须是和2相连
  • 1.如果结点1不和结点2相连,加边 ans++
  • 2.如果相连遍历dfs(2),如果结点2和3相连dfs(3),依次类推
  • 如果不和3相连并且不与其他任何结点相连,返回上一结点,因为在结点1加边结果不会比结2差
  • 如果结点2和结点3以外的边相连接则需要加边ans++

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
int t,n,m,u,v,ans,tot;    //变量tot计算当前遍历到哪一个数
vector<int>edge[maxn];

void dfs(int u)
{
    if(u == n+1) return;
    for(auto x:edge[u])
    {
        if(x < tot) continue;
        while( x >= tot )
        {
            if(x==tot) tot++, dfs(x);
            else 
            {
                tot++; ans++; dfs(tot-1);
            }
        }
    }
}

int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            edge[u].push_back(v);
            edge[v].push_back(u);
        }
        //题目中按照DFS顺序排列所以对邻接表中的元素排序
        for(int i=1;i<=n;i++)
            sort(edge[i].begin(), edge[i].end());
        //保证1~n的点全部被遍历一遍
        edge[1].push_back(n+1);
        tot=2, ans=0;
        dfs(1);
        printf("%d\n",ans);
        for(int i=1;i<=n;i++) edge[i].clear();
    }
    return 0;
}

posted on 2023-01-15 20:37  IR101  阅读(14)  评论(0编辑  收藏  举报  来源