zoukankan      html  css  js  c++  java
  • CF1296F Berland Beauty (Tree, dfs/bfs, LCA)

    题目链接

    题解:

    方法1: 走一遍dfs/bfs得到u->v的路径。每一个m,保证走过得边>=此最小值。再走一遍m,看路径的最小值是否是提供的。

    #include <bits/stdc++.h>
    # define LL long long
    using namespace std;
    
    int n;
    int m;
    void bfs(int u, vector<pair<int,int>> &p, vector<vector<pair<int,int>>> &adj){
        queue<int> q;
        q.push(u);
        while(!q.empty()){
            int cur=q.front();
            q.pop();
            for(auto as:adj[cur]){
                int v=as.first;
                if(v==p[cur].first) continue;
                int e=as.second;
    
                p[v].first=cur;
                p[v].second=e;
                q.push(v);
            }
        }
    }
    
    int main(){
        scanf("%d", &n);
        vector<vector<pair<int,int>>> adj(n+1);
        for(int i=1;i<=n-1;++i){
            int u,v;
            scanf("%d %d", &u, &v);
            adj[u].push_back(make_pair(v,i));
            adj[v].push_back(make_pair(u,i));
        }
    
        vector<vector<pair<int,int>>> pre(n+1,vector<pair<int,int>>(n+1));
        for(int i=1;i<=n;++i){
            pre[i][i]=make_pair(0,0);
            bfs(i,pre[i], adj);
        }
    
        scanf("%d", &m);
        vector<int> val(n,0);
        vector<vector<int>> query(m+1,vector<int>(3,0));
        for(int i=1;i<=m;++i){
            scanf("%d %d %d", &query[i][0], &query[i][1], &query[i][2]);
        }
        for(int i=1;i<=m;++i){
            int u=query[i][0];
            int v=query[i][1];
            int f=query[i][2];
            while(true){
                int pree=pre[u][v].second;
                int prev=pre[u][v].first;
                val[pree]=max(val[pree],f);
                v=prev;
                if(v==u) break;
            }
        }
    
        for(int i=1;i<=m;++i){
            int u=query[i][0];
            int v=query[i][1];
            int f=query[i][2];
            int mx=1000000+10;
            while(true){
                int pree=pre[u][v].second;
                int prev=pre[u][v].first;
                mx=min(mx,val[pree]);
                v=prev;
                if(v==u) break;
            }
            if(mx!=f){
                printf("-1");
                return 0;
            }
        }
        for(int i=1;i<=n-1;++i){
            if(val[i]==0) printf("100 ");
            else printf("%d ", val[i]);
        }
        return 0;
    }

    方法2:

    LCA

    #include <bits/stdc++.h>
    # define LL long long
    using namespace std;
    
    const int maxn=5000+10;
    int n;
    int m;
    int lg[maxn];
    int depth[maxn];
    int fa[maxn][22];
    int edgenum[maxn];
    int w[maxn];
    
    struct Edge{
        int to, next, idx;
    }e[maxn<<1];
    int head[maxn];
    int en;
    
    void add(int from, int to, int idx){
        e[en].next=head[from];
        e[en].to=to;
        e[en].idx=idx;
        head[from]=en;
        ++en;
    }
    
    void dfs(int u, int pre){
        depth[u]=depth[pre]+1;
        fa[u][0]=pre;
        for(int i=1;i<=lg[depth[u]-1];++i){
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].to;
            int id=e[i].idx;
            if(v==pre) continue;
            edgenum[v]=id;
            dfs(v,u);
        }
    }
    
    int LCA(int p, int q){
        if(depth[p]<depth[q]) swap(p,q);
    
        while(depth[p]>depth[q]){
            p=fa[p][lg[depth[p]-depth[q]]];
        }
        if(p==q) return p;
        for(int i=lg[depth[p]-1];i>=0;--i){
            if(fa[p][i]!=fa[q][i]){
                p=fa[p][i];
                q=fa[q][i];
            }
        }
        return fa[p][0];
    }
    
    void modify(int u, int v, int val){
        int lca=LCA(u,v);
        while(u!=lca){
            w[edgenum[u]]=max(w[edgenum[u]],val);
            u=fa[u][0];
        }
        while(v!=lca){
            w[edgenum[v]]=max(w[edgenum[v]],val);
            v=fa[v][0];
        }
    }
    
    int que(int u, int v){
        int mi=1000001;
        int lca=LCA(u,v);
        while(u!=lca){
            mi=min(mi,w[edgenum[u]]);
            u=fa[u][0];
        }
        while(v!=lca){
            mi=min(mi,w[edgenum[v]]);
            v=fa[v][0];
        }
        return mi;
    }
    
    int main(){
        memset(head,-1,sizeof(head));
        scanf("%d", &n);
    
        for(int i=1;i<=n-1;++i){
            int u,v;
            scanf("%d %d", &u, &v);
            add(u,v,i);
            add(v,u,i);
        }
    
        scanf("%d", &m);
        vector<vector<int>> query(m+1,vector<int>(3,0));
        for(int i=1;i<=m;++i){
            scanf("%d %d %d", &query[i][0], &query[i][1], &query[i][2]);
        }
    
        lg[1]=0;
        lg[2]=1;
        for(int i=3;i<=n;++i){
            if(i==(1<<(lg[i-1]+1))){
                lg[i]=lg[i-1]+1;
            }else{
                lg[i]=lg[i-1];
            }
        }
    
        dfs(1,0);
    
        for(int i=1;i<=m;++i){
            int u=query[i][0];
            int v=query[i][1];
            int val=query[i][2];
            modify(u,v,val);
        }
    
        for(int i=1;i<=m;++i){
            int u=query[i][0];
            int v=query[i][1];
            int val=query[i][2];
            int q=que(u,v);
            if(q!=val){
                printf("-1");
                return 0;
            }
        }
        for(int i=1;i<=n-1;++i){
            if(w[i]==0) w[i]=1;
            printf("%d ", w[i]);
        }
        return 0;
    }
  • 相关阅读:
    android一些小的问题
    Android知识细节
    在Windows登录Linux的一些工具
    Android studio字体调整
    在Android Studio中自动添加import以及快捷键
    设计模式(十三) 职责链(chain of responsibility)
    设计模式(十二):bridge模式
    linux 进程通信 管道
    信号量sem
    一道求递增数的题目
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12263876.html
Copyright © 2011-2022 走看看