题意: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<bits/stdc++.h>
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 <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <cctype>
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;
}

本文探讨了一种算法,用于解决博客写作者Jony在面对博客间引用关系时,如何合理分配不同主题的问题,确保引用的博客不涵盖相同主题,同时满足所有主题1-1的覆盖需求。

被折叠的 条评论
为什么被折叠?



