P8066 Fan Groups

考虑先去除图上边权为 \(1\) 的边然后跑一个 tarjan 缩强联通分量。

现在图上有若干个 DAG,每一个 DAG 只能有一个度数为 \(0\) 的强联通分量,不然显然无解。

然后这一个 DAG 的构造方案就是找到度数为 \(0\) 的强联通分量,然后输出其中一个点,剩下的随便你排布。

现在考虑边权为 \(1\) 的边带来的影响。

我们设 \(d_i\) 表示 \(i\) 所在的 DAG 编号,那么一条边 \((x,y,1)\) 限制的实际上就是 \(d_y\) 要在 \(d_x\) 之前。

建出图然后拓扑排序即可。时间复杂度 \(O(n+m)\)为啥有紫呢?

//code by Emissary
#include<bits/stdc++.h>

#define pb push_back

using namespace std;

const int MAXN = 2e5+5;

int n, m;
int hd, tl, Q[MAXN], fa[MAXN];
int stk[MAXN], bel[MAXN], topf, tot;
int low[MAXN], dfn[MAXN], du[MAXN], colcnt;
int head[MAXN], ne[MAXN<<1], to[MAXN<<1], bl[MAXN], cnt;

bool ins[MAXN], vis[MAXN];

vector<int> node[MAXN], f[MAXN];

inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}

inline void add(int x, int y){++cnt;to[cnt]=y;ne[cnt]=head[x];head[x]=cnt;}

inline void tarjan(int x){
	low[x]=dfn[x]=++tot; ins[x]=1; stk[++topf]=x;
	for(int i=head[x];i;i=ne[i]){
		if(dfn[to[i]]){
			if(ins[to[i]]) low[x]=min(low[x],dfn[to[i]]);
		}
		else tarjan(to[i]), low[x]=min(low[x],low[to[i]]);
	}
	if(dfn[x]==low[x]){
		stk[topf+1]=0; ++colcnt;
		while(stk[topf+1]!=x){
			int t=stk[topf]; bel[t]=bl[t]=colcnt;
			ins[stk[topf]]=0; node[colcnt].pb(t);
			--topf;
		}
	}
	return ;
}

inline void dfs(int x, int b){
	bel[x]=b; f[b].pb(x);
	for(auto i:node[x]) vis[i]=1;
	for(auto i:node[x]){
		for(int j=head[i];j;j=ne[j]){
			if(vis[to[j]]) continue;
			dfs(bl[to[j]],b);			
		}
	}
	return ;
}

signed main(){
	ios::sync_with_stdio(0);
	vector<pair<int,int> > E; cin >> n >> m;
	for(int i=1;i<=n;++i) fa[i]=i;
	for(int i=1;i<=m;++i){
		int x, y, c;
		cin >> x >> y >> c;
		if(c==0) add(x,y), fa[find(x)]=find(y);
		else E.pb(make_pair(x,y));	
	}
	int tot=0, all=0;
	for(int i=1;i<=n;++i) tot+=find(i)==i;
	for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
	for(int i=1;i<=n;++i) for(int j=head[i];j;j=ne[j]) if(bel[i]!=bel[to[j]]) du[bel[to[j]]]++;
	for(int i=1;i<=colcnt;++i) all+=du[i]==0;
	if(tot!=all) return cout << -1, 0; hd=1, tl=0;
	for(auto &i:E) i.first=bel[i.first], i.second=bel[i.second];
	for(int i=1;i<=colcnt;++i) if(du[i]==0) dfs(i,all), all--;
	memset(du,0,sizeof du); memset(head,0,sizeof head); cnt=0; 
	for(auto i:E) add(bel[i.second],bel[i.first]), du[bel[i.first]]++;
	for(int i=1;i<=tot;++i) if(du[i]==0) Q[++tl]=i; int t; vector<int> ans;
	while(hd<=tl){
		t=Q[hd++];
		for(auto i:f[t]) for(auto j:node[i]) ans.pb(j);
		for(int i=head[t];i;i=ne[i]) if((--du[to[i]])==0) Q[++tl]=to[i];
	}
	if(tl!=tot) cout << -1;
	else for(auto i:ans) cout << i << ' ';
	return 0;
}





































































posted @ 2024-02-08 20:01  OccDreamer  阅读(28)  评论(0)    收藏  举报