[bzoj5485][Usaco2018 Dec][亂搞]The Cow Gathering

Description

奶牛們從世界各地聚集起來參加一場大型聚會。總共有N頭奶牛,N?1對奶牛互爲朋友。每頭奶牛都可以通過一些朋
友關係認識其他每頭奶牛。她們玩得很開心,但是現在到了她們應當離開的時間了,她們會一個接一個地離開。她
們想要以某種順序離開,使得只要至少還有兩頭奶牛尚未離開,所有尚未離開的奶牛都還有沒有離開的朋友。此外
,由於行李寄存的因素,有M對奶牛(ai,bi)必須滿足奶牛ai要比奶牛bi先離開。注意奶牛ai和奶牛bi可能是朋友,
也可能不是朋友。幫助奶牛們求出,對於每一頭奶牛,她是否可以成爲最後一頭離開的奶牛。可能會發生不存在滿 足上述要求的奶牛離開順序的情況。

Input

輸入的第1行包含兩個空格分隔的整數N和M。
輸入的第2≤i≤N行,每行包含兩個整數xi和yi,滿足1≤xi,yi≤N,xi≠yi,表示奶牛xi和奶牛yi是朋友關係。
輸入的第N+1≤i≤N+M行,每行包含兩個整數ai和bi,滿足1≤ai,bi≤N,ai≠bi,表示奶牛ai必須比奶牛bi先離開聚會。
輸入保證1≤N,M≤10^5

Output

輸出N行,每行包含一個整數di,如果奶牛i可以成爲最後一頭離開的奶牛,則di=1,否則di=0

Sample Input

5 1

1 2

2 3

3 4

4 5

2 4

Sample Output

0

0

1

1

1

題解

我的做法涼涼嚕…
然後tkj告訴了我一個重要的結論,就是合法的點一定是一個連通塊
然後就會做了
我們首先先可以注意到,每次刪掉的一定是葉子節點
那麼什麼情況下一個點不合法呢
不妨設有向邊x->y表示x必須在y之前走
那麼以某個點爲根,不存在任意一個父親通過上面有向邊的DAG走能到達自己的子樹裏的點的
這個點就是合法的
那我的做法就是考慮每條邊的貢獻,每次讓一些邊涼掉
但是這樣需要知道DAG中x能走到的點與某一個連續範圍的點的交集
然後就涼了…
但是有了上面那個結論的話,我們可以暴力找出第一個合法點
具體怎麼找就每次刪去一個沒有限制的葉子節點
最後留下來一個點就是了…否則你找不到其他合法點的
那麼再考慮另外怎麼樣,畫圖模擬可知只要這個點沒有出邊那麼就是合法的
於是就沒有了…
有沒有能告訴我我的做法怎麼做的呀麻煩評論一下吧qwq

哦我的做法是真的…
就你發現,x能走到的點一定只在他一棵子樹裏面
否則的話,x在任何一個合法的時間刪掉都會造成出現兩個連通塊
那麼你只需要記錄一下dfs序的min和max,DAG反向轉移就行了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int stack[20];
inline void write(LL x)
{
	if(x<0){putchar('-');x=-x;}
    if(!x){putchar('0');return;}
    int top=0;
    while(x)stack[++top]=x%10,x/=10;
    while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(LL x){write(x);putchar('\n');}
const int MAXN=1000005;
struct edge{int x,y,next;}a[2*MAXN];int len,last[MAXN];
void ins(int x,int y){len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}

bool ok[MAXN];
int ot[MAXN],in[MAXN];
vector<int> vec[MAXN];

void dfs(int x,int fa)
{
	if(ot[x])return ;
	ok[x]=true;
	for(int k=last[x];k;k=a[k].next)
	{
		int y=a[k].y;
		if(y!=fa)dfs(y,x);
	}
}
int n,m,du[MAXN];
queue<int> li;
int main()
{
	n=read();m=read();
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read();
		ins(x,y);ins(y,x);
		du[x]++;du[y]++;
	}
	for(int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		vec[x].push_back(y);ot[x]++;in[y]++;
	}
	int cnt=n;
	for(int i=1;i<=n;i++)if(!in[i]&&du[i]==1)li.push(i);
	int o;
	while(!li.empty())
	{
		int x=li.front();li.pop();
		cnt--;o=x;
		for(int i=0;i<vec[x].size();i++)
		{
			int y=vec[x][i];
			in[y]--;if(du[y]==1&&in[y]==0)li.push(y);
		}
		for(int k=last[x];k;k=a[k].next)
		{
			du[a[k].y]--;
			if(du[a[k].y]==1&&in[a[k].y]==0)li.push(a[k].y);
		}
	}
	if(cnt!=0){for(int i=1;i<=n;i++)pr2(0);return 0;}
	dfs(o,0);
	for(int i=1;i<=n;i++)pr2(ok[i]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章