2021ICPC 四川省赛(bfs+dp,dfs)

E. Don't Really Like How The Story Ends

题意

有一个图包含 \(n\) 个点,要求添加最少的边使得构成 \(1...n\)\(dfs\)

数据范围

\(1<=n,m<=10^5\)

多组测试样例

输入

3
2 3
1 1
1 2
2 1
4 1
1 4
4 2
1 2
3 4

输出

0
2
1

分析

本着非必要的时候不添边的原则,只有当 \([1,i-1]\) 全部遍历完成时,且 \(i\) 节点没有一条合法的边时,才可以添加这条边;

如何判断一个节点存在合法边就是从当前叶子节点向上遍历,只要存在一个父节点联通 \(i\) 说明合法,如果到达 \(root=1\),还是没有便是不合法

$hint: $ 可能有很多节点都是游离的

代码

const int N = 1e5 + 5;
  
    int n, m, k, _;
    int a[N];
    vector<int> g[N];
    int ed, ans;
    int vis[N];
 
void dfs(int u)
{
    // vis[u] = 1;
    for(int i = 0; i < g[u].size(); i ++){
        int v = g[u][i];
        if(v < ed) continue;
        if(v == ed){
            ed ++;
            dfs(v);
        }
        else{ 
            ans ++;
            ed ++;
            i --;
            dfs(ed - 1);
        }
    }
    while(ed <= n && u == 1){
        ed ++;
        ans ++;
        dfs(ed - 1);
    }
}
 
void clear()
{
    for(int i = 1; i <= n; i ++) g[i].clear();
}
 
signed main()
{
    // IOS;
    rush(){
        sdd(n, m);
        rep(i, 1, m){
            int x, y;
            sdd(x, y);
            if(x > y) swap(x, y);
            if(x != y) g[x].pb(y);
        }
        for(int i = 1; i <= n; i ++){
            sort(g[i].begin(), g[i].end());
            g[i].erase(unique(g[i].begin(), g[i].end()), g[i].end());
        }
        ed = 2;
        ans = 0;
        dfs(1);
        pd(ans);
        clear();
    }
    // PAUSE;
    return 0;
}






L. Spicy Restaurant

题意

有一个图包含 \(n\) 个点,每个节点都有一个辣度值,\(q\) 此询问,每次询问给出人的位置以及接受的最大辣度值,求最近的可以接受的辣度值离自己多远

数据范围

\(1<=n,m<=10^5\)

\(1<=q<=5*10^5\)

\(1<=a[i]<=100\)

输入

4 4 5
5 4 2 3
1 2
2 3
3 4
4 1
1 1
1 2
1 3
1 4
1 5

输出

-1
2
1
1
0

分析

\(dp[i][j]\) 当前 \(i\) 位置辣度值为 \(j\) 的最近距离

可以利用 \(bfs\) 求出来所有的值

题目建图不可以用 \(vector\),以下代码不可以保证通过

代码

const int N = 1e5 + 5;
 
    int n, m, k, _;
    int a[N];
    int dp[N][100 + 5];
    vector<int> g[N];

void bfs(int w)
{
    queue<int> q;
    for(int i = 1; i <= n; i ++){
        if(a[i] == w){
            q.push(i);
            dp[i][w] = 0;
        }
    }
    while(q.empty() == 0){
        int u = q.front();
        q.pop();
        for(auto v : g[u]){
            if(dp[v][w] != inf) continue;
            dp[v][w] = min(dp[v][w], dp[u][w] + 1);
            q.push(v);
        }
    }
}

signed main()
{
    // IOS;
    int q;
    while(~ sddd(n, m, q)){
        int maxx = 0;
        rep(i, 1, n) sd(a[i]), maxx = max(maxx, a[i]);
        rep(i, 0, n) rep(j, 0, maxx) dp[i][j] = inf;
            int x, y;
        rep(i, 1, m){
            sdd(x, y);
            g[x].pb(y);
            g[y].pb(x);
        }
        for(int i = 1; i <= maxx; i ++){
            bfs(i);
        }
        // rep(i, 1, n) rep(j, 1, 5) dbg(dp[i][j]);
        for(int i = 1; i <= n; i ++){
            for(int j = 1; j <= maxx; j ++){
                dp[i][j] = min(dp[i][j], dp[i][j - 1]);
            }
        }
            int pos, val;
        while(q --> 0){
            sdd(pos, val);
            if(dp[pos][val] == inf) dp[pos][val] = -1;
            pd(dp[pos][val]);
        }
    }
    // PAUSE;
    return 0;
}
posted @ 2021-11-11 10:53  Bcoi  阅读(234)  评论(0)    收藏  举报