CF1361A Johnny and Contribution(拓扑排序)

题意:

给出一个图,每个顶点有一个目标权值,请你设计一个访问顺序,使得节点被访问时的权值是目标权值。

节点当前权值设定为与它相连的所有节点中已被访问的节点的权值之外的最小值。

题解:

合法的条件就是,每个节点周围必须有w[i]-1个不同的节点,且最大值要是w[i]。

然后考试的时候我写了一个类似于拓扑排序的算法,在入队的部分根据题意乱搞了一下。。。

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+100;
int visit[maxn];
int w[maxn];//每个顶点的目标
int s[maxn];//每个顶点的初始值,都为1
queue<int> q;
vector<int> ans;
int n,m;
vector<int> g[maxn];
set<int> st[maxn];
void topOrder () {
    for (int i=1;i<=n;i++) if (s[i]==w[i])  {
        q.push(i),visit[i]=1;
        //break;
    }
    while (!q.empty()) {
        int u=q.front();
        q.pop();
        ans.push_back(u);
        for (int i=0;i<g[u].size();i++) {
            int v=g[u][i];
            if (visit[v]) continue;
            if (s[v]<s[u]+1) s[v]=s[u]+1;
            if (s[v]==w[v]) {
                q.push(v);
                visit[v]=1;
            }
            
        }
    }
}
struct node {
    int u,v;
};
vector<node> vi;
int main () {
    scanf("%d%d",&n,&m);
    for (int i=0;i<m;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
        vi.push_back({x,y});
    }
    for (int i=1;i<=n;i++) scanf("%d",&w[i]),s[i]=1; 
    for (int i=0;i<vi.size();i++) {
        int u=vi[i].u;
        int v=vi[i].v;
        if (w[u]<w[v]) st[v].insert(w[u]);
        if (w[v]<w[u]) st[u].insert(w[v]);
        if (w[vi[i].u]==w[vi[i].v]) {
            printf("-1
");
            return 0;
        }
    }
    for (int i=1;i<=n;i++) {
        if (st[i].size()<w[i]-1) {
            printf("-1
");
            return 0;
        }
    }
    topOrder();
    if (ans.size()<n) {
        printf("-1
");
        return 0;
    }
    for (int i=0;i<ans.size();i++) printf("%d ",ans[i]);
    return 0;
} 
原文地址:https://www.cnblogs.com/zhanglichen/p/13048385.html