参考:http://blog.youkuaiyun.com/aozil_yang/article/details/51866239
大体题意:
一个家庭聚会,每个人都想送出礼物,送礼规则是 一个人 先看名单列表,发现第一个祖先 就会送给他礼物,然后就不送了,如果他没找到礼物 他会伤心的离开聚会!告诉你m个祖先关系,和每个人想给谁送!让你求出名单列表!
注意 自己是自己的祖先。
思路:
想一想规则可以知道: 如果祖先关系是 D - > C -> B -> A 那么如果A想给D送礼物,那么BC也必须给D送礼物 如果B 送给C 那么B第一个找到的祖先是C A也应该送给C这就矛盾了!也就是说只要 A想送的礼物和祖先一样或者送给自己就可以了!
vector<int> ans;
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void add_edge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u)
{
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(fa[v] != fa[u] && fa[v] != v)
flag = 0;
dfs(v);
}
if(fa[u] == u)
ans.push_back(u);
}
int main()
{
int t,C = 1;
//scanf("%d",&t);
while(scanf("%d%d",&n,&m) != EOF)
{
init();
memset(dep,0,sizeof(dep));
for(int i = 0; i < m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
dep[v]++;
}
for(int i = 1; i <= n; i++)
scanf("%d",&fa[i]);
flag = 1;
ans.clear();
for(int i = 1; i <= n; i++)
if(!dep[i])
dfs(i);
if(!flag)
printf("-1\n");
else
{
printf("%d\n",ans.size());
for(int i = 0; i < ans.size(); i++)
printf("%d\n",ans[i]);
}
}
return 0;
}
然后最强的就是看到师兄用的树链剖分做的。。。ORZ
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <vector>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define N 100020
#define M 220000
#define ls (i << 1)
#define rs (ls | 1)
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
int n, m;
int fst[N], nxt[M], vv[M], e;
int dep[N], fa[N];
int tp[N], son[N], sz[N], tid[N], ed[N], lab[N], dc;
int k;
vector<int> g[N];
bool vis[N];
int id[N];
int a[N];
int cnt[N << 2];
void init() {
memset(fst, -1, sizeof fst);
e = 0;
}
void add(int u, int v) {
vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
}
void dfs(int u, int p, int d) {
vis[u] = 1;
sz[u] = 1;
dep[u] = d;
int mx = 0;
for(int i = fst[u]; ~i; i = nxt[i]) {
int v = vv[i];
dfs(v, u, d + 1);
sz[u] += sz[v];
if(sz[v] > mx) mx = sz[u], son[u] = v;
}
}
void dfs2(int u, int anc) {
tid[u] = ++dc;
lab[dc] = u;
tp[u] = anc;
if(son[u]) dfs2(son[u], anc);
for(int i = fst[u]; ~i; i = nxt[i]) {
int v = vv[i];
if(v != son[u]) dfs2(v, v);
}
ed[u] = dc;
}
bool cmp(int i, int j) {
return tid[i] > tid[j];
}
void update(int x, int ll, int rr, int i) {
cnt[i]++;
if(ll == rr) return;
if(x <= md) update(x, lson);
else update(x, rson);
}
int query(int l, int r, int ll, int rr, int i) {
if(ll == l && rr == r) return cnt[i];
if(r <= md) return query(l, r, lson);
if(l > md) return query(l, r, rson);
return query(l, md, lson) + query(md + 1, r, rson);
}
int query(int u, int v) {
int ret = 0;
while(tp[u] != tp[v]) {
if(dep[tp[u]] > dep[tp[v]]) swap(u, v);
ret += query(tid[tp[v]], tid[v], 1, n, 1);
v = fa[tp[v]];
}
if(dep[u] > dep[v]) swap(u, v);
ret += query(tid[u], tid[v], 1, n, 1);
return ret;
}
int main() {
scanf("%d%d", &n, &m);
init();
for(int i = 1; i <= m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
fa[v] = u;
add(u, v);
}
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
g[a[i]].push_back(i);
}
for(int i = 1; i <= n; ++i) {
if(fa[i] == 0) {
dfs(i, 0, 0);
}
}
for(int i = 1; i <= n; ++i) {
if(fa[i] == 0) {
dfs2(i, i);
}
}
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; ++i) vis[a[i]] = 1;
for(int i = 1; i <= n; ++i) if(vis[i]) id[++k] = i;
sort(id + 1, id + k + 1, cmp);
bool f = 1;
for(int i = 1; i <= k; ++i) {
int u = id[i];
for(int j = 0; j < g[u].size(); ++j) {
int v = g[u][j];
if(query(u, v) > 0) {
f = 0;
break;
}
}
if(!f) break;
update(tid[u], 1, n, 1);
}
if(!f) puts("-1");
else {
printf("%d\n", k);
for(int i = 1; i <= k; ++i)
printf("%d\n", id[i]);
}
return 0;
}