Codeforces Round #647 (Div. 2) D. Johnny and Contribution(贪心)

题意:Jony要写n篇博客,每篇博客的内容只能覆盖一个主题,但一个主题可以被多篇博客覆盖。在博客与博客之间可以相互引用,但是相互引用的博客不能涵盖相同的主题,否则博客是无效的。给出Jony要写的博客之间的相互引用关系,他在写博客的时候会依照这个引用关系来安排写博客的顺序,因此他在写博客的时候会首先查看他要引用的博客的主题,然后选出没有被覆盖的且主题编号最小的主题写入本篇博客。例如:若要的这篇博客引用的博客覆盖了主题1,3,2,5,那么这篇博客就应该要选择主题4编写。问是否存在一个写博客的顺序满足博客之间的相互引用。

思路:题意精简之后就是有N个点M条边,每个点有特定属性Ti,对于任意一点u,与u直接相连的所有点中不能有与点u属性相同的点,并且直接相连的点的属性必须存在1-1的所有数。那么首先比较简单的可以判断的是与u直接相连的点中是否存在属性一样的点,只要记录下所有点的属性值就可以。第二个要判断的是是否存在1-1在与点u相连的点中,只需要将与点u相连的点的属性放到set里,然后1-1去查询就可以了。如果这两个条件都满足,则就可以安排出顺序。但是由于具体的安排需要的是:对于当前要安排的位置P,要求是1P-1中与安排在这个位置的点u相连的点中不能有重复属性且必须1~ - 1全都出现,所以可以sort升序排序属性值,根据属性值从小到大安排,这样只要满足以上两个条件,此安排就必定可行。
方法1:思路:贪心,显然可以知道要从小到大涂,首先我们把为期望颜色为1的都涂掉,然后对每个u判断一下相邻结点v vv的期望颜色是否也为1如果是v 的期望颜色++.依次类推。因为是从小开始涂的,所以保证当前比u颜色小的都涂了。所以就可以直接判断了。只要当前结点u uu的期望颜色不是原来的颜色i就可以直接返回−1了。注意初始化一下期望颜色为1即可。

#include
using namespace std;
typedef long long ll;
const int N=5e5+5;
#define mst(a) memset(a,0,sizeof a)
int num[N],n,m;
vector<int>e[N],ans,col[N];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,u,v;i<=m;i++){
		scanf("%d%d",&u,&v);
		e[u].push_back(v);
		e[v].push_back(u);
	}
	for(int i=1;i<=n;i++){
		int c;
		scanf("%d",&c);
		col[c].push_back(i);
		num[i]=1;
	}
	for(int i=1;i<=n;i++){
		  for(auto u:col[i]){
		  	 	if(num[u]!=i)  puts("-1"),exit(0);
		  	 	for(auto v:e[u])
		  	 		if(num[v]==i) num[v]++;
		  	 	ans.push_back(u);
		  }
	}
	for(auto i:ans) printf("%d ",i); 
	return 0;
} 

方法二:首先主题数肯定是贪心的从最小开始找点的,然后对于每一个点,比如期望为3 33的主题数的周围有着1,2 1,21,2主题的节点,那么此时的最小可以的主题数是3 33,如果周围有一个主题是3 33的话,那么此时最小的主题应该就是4 44了,这样期望的主题数应该也为4 44,很明显,不符合条件了,明白了细节,直接模拟一下就行了。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
int xxxxxxxxx = 1;
inline void outi(int x) {if (x > 9) outi(x / 10);putchar(x % 10 + '0');}
inline void outl(ll x) {if (x > 9) outl(x / 10);putchar(x % 10 + '0');}
inline void debug(ll x) {cout << xxxxxxxxx++ << " " << x << endl;}
inline void debugs(string s) {cout << s << endl;}
const int maxn = 5e5 + 10;
struct NODE {
    int val;
    int id;
    bool friend operator < (NODE a, NODE b) {
        return a.val < b.val;
    }
};
NODE node[maxn];
veci edge[maxn];
bool book[maxn] = {false};
int col[maxn];
int main() {
    int n, m;
    read(n), read(m);
    for (int i = 0; i < m; i++) {
        int u, v;
        read(u), read(v);
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    for (int i = 1; i <= n; i++) {
        read(node[i].val);
        node[i].id = i;
        col[i] = node[i].val;
    }
    sort(node + 1, node + n + 1);
    for (int i = 1; i <= n; i++) {
        int ans = 1;
        int u = node[i].id;
        set<int> st;
        for (int j = 0; j < edge[u].size(); j++) {
            int v = edge[u][j];
            if (col[u] == col[v]) {
                printf("-1\n");
                return 0;
            }
            st.insert(col[v]);
        }
        for (int j = 1; j < col[u]; j++) {
            if (st.find(j) == st.end()) {
                printf("-1\n");
                return 0;
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        printf("%d ", node[i].id);
    }
    return 0;
}


你可能感兴趣的:(思维,读题)