Loading

【考后总结】6 月西安 NOI 模拟赛 5

Page Views Count

6.24 冲刺国赛模拟 24

T2 简单图论题

原题:QOJ-8140 Customs Controls 2

构造题。

这个限制可以进一步加强到对于每个节点 \(u\)\(1\to u\) 的路径权值都相等,定义为 \(d_u\)

于是对 \(u\) 连边的两个节点的 \(d\) 一定相等,进而可以把所有相等的缩到一起,且这些点直接不能连边(点权至少是 \(1\)),这样可以对处理过后的图跑最长路,如果存在环一定无解。

最后的答案就是任意找一条连向 \(v\) 的边 \((u,v)\),其中 \(w_v=d_v-d_u\)

点击查看代码
int t;
int n,m;
vector<int> E1[maxn],E2[maxn],E3[maxn];
int bel[maxn],id[maxn];
int find(int x){
	if(x==bel[x]) return x;
	return bel[x]=find(bel[x]);
}
int deg[maxn];
int f[maxn],g[maxn],cnt;
int main(){
	freopen("dag.in","r",stdin);
	freopen("dag.out","w",stdout);
	t=read();
	while(t--){
		n=read(),m=read();
		for(int i=1;i<=n;++i) E1[i].clear(),E2[i].clear(),E3[i].clear();
		for(int i=1;i<=m;++i){
			int u=read(),v=read();
			E1[u].push_back(v),E2[v].push_back(u);
		}
		for(int i=1;i<=n;++i) bel[i]=i,id[i]=0,deg[i]=0; 
		for(int u=1;u<=n;++u){
			for(int i=1;i<(int)E2[u].size();++i){
				int v1=E2[u][i-1],v2=E2[u][i];
				int f1=find(v1),f2=find(v2);
				// printf("%d %d %d %d\n",v1,v2,f1,f2);
				bel[f2]=f1;
			}
		}
		int tot=0;
		for(int i=1;i<=n;++i){
			// printf("%d %d\n",i,find(i));
			if(find(i)==i) id[i]=++tot;
		}
		bool chk=1;
		for(int u=1;u<=n;++u){
			for(int v:E1[u]){
				if(find(u)==find(v)) chk=0;
				else{
					E3[id[find(u)]].push_back(id[find(v)]);
					++deg[id[find(v)]];
				}
			}
		}
		queue<int> q;
		if(deg[1]) chk=0;
		f[1]=1;
		q.push(1);
		cnt=0;
		while(!q.empty()){
			int u=q.front();
			q.pop();
			++cnt;
			for(int v:E3[u]){
				f[v]=f[u]+1;
				--deg[v];
				if(!deg[v]) q.push(v);
			}
		}
		if(cnt<tot) chk=0;
		g[1]=1;
		for(int v=2;v<=n;++v){
			int u=E2[v][0];
			g[v]=f[id[find(v)]]-f[id[find(u)]];
		}
		if(!chk) printf("No\n");
		else{
			printf("Yes\n");
			for(int i=1;i<=n;++i) printf("%d ",g[i]);
			printf("\n");
		}
	}
	return 0;
}
posted @ 2023-06-27 20:01  SoyTony  阅读(25)  评论(0编辑  收藏  举报