首页 > 其他分享 >P9697 Canvas 题解

P9697 Canvas 题解

时间:2024-02-08 20:14:14浏览次数:30  
标签:Canvas 联通 P9697 题解 long int MAXN 分量 define

首先观察到有一个关键性质是 \(1 \leq x_i,y_i \leq 2\)。

那么我们贪心的考虑我们肯定会将 \((x,y)=(1,1)\) 的在一开始操作,\((x,y)=(2,2)\) 的最后操作。

也就是说现在没有固定的是 \((x,y)=(1,2)\) 和 \((x,y)=(2,1)\) 的。

我们不妨令 \((x,y)=(1,2)\),然后连边 \((l,r)\)。

然后我们需要依次选择每一条边 \((u,v)\),这个操作相当于赋值 \(a_v =2\) 和赋值 \(a_u=1\)。

然后我们可以容易构造出来一个强联通分量中经过一系列操作至多有一个 \(a=1\) 的节点,并且一定有一个 \(a=1\) 的节点,具体的随便搜出一个这个分量中的 dfs 树然后从叶子开始操作即可。

那么缩强联通分量使图变成 DAG 之后如果一个点没有前驱那么意味着这一个强联通分量有一个点 \(a=1\),如果有前驱那么我们可以将这一个强联通分量内的点全操作成 \(2\)。

建出图跑一个 tarjan 然后跑一个拓扑排序即可。

对于 \((x,y)=(2,2)\) 的限制,我连了边 \((0,x)\) 和 \((0,y)\),似乎更好考虑一些。

代码写的有点丑和冗余。

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

#define fi first
#define se second
#define vc vector
#define db double
#define ll long long
#define mk make_pair
#define pb push_back
#define PI pair<int,int>
#define ull unsigned long long
#define err cerr << "   -_-   " << endl
#define debug cerr << " ------------------- " << endl

#define input(x) freopen(#x".in","r",stdin)
#define output(x) freopen(#x".out","w",stdout)

#define NO puts("No")
#define YES puts("Yes")

//#define int long long

using namespace std;

namespace IO{
	inline int read(){
		int X=0, W=0; char ch=getchar();
		while(!isdigit(ch)) W|=ch=='-', ch=getchar();
		while(isdigit(ch)) X=(X<<1)+(X<<3)+(ch^48), ch=getchar();
		return W?-X:X;
	}
	inline void write(int x){
		if(x<0) x=-x, putchar('-');
		if(x>9) write(x/10);
		putchar(x%10+'0');
	}
	inline void sprint(int x){write(x), putchar(32);}
	inline void eprint(int x){write(x), putchar(10);}
}using namespace IO;

const int MAXN = 5e5+5;

vc<PI> G[MAXN];
vc<int> P[MAXN];

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

bool mark[MAXN], ins[MAXN], vis[MAXN], ind[MAXN];

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

inline void tarjan(int x){
	stk[++topf]=x; dfn[x]=low[x]=++tot; ins[x]=1;
	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(low[x]==dfn[x]){
		int t; stk[topf+1]=-1; ++colcnt;
		while(stk[topf+1]!=x){
			t=stk[topf];
			ins[t]=0; bel[t]=colcnt; node[colcnt]=t;
			--topf;
		}
	}
	return ;
}

inline void DFS(int x){//这一部分是搜出一个强联通分量内的 dfs 树
	vis[x]=1;
	for(int i=head[x];i;i=ne[i]){
		if(vis[to[i]] || bel[to[i]]!=bel[x]) continue;
		DFS(to[i]); P[bel[x]].pb(weight[i]); ind[weight[i]]=1;
	}
	return ;
}

inline void solve(){
	int a, b, c, d; vc<int> A, B;
	n=read(), m=read(); cnt=0; tot=0; colcnt=0;
	for(int i=0;i<=n;++i) vis[i]=0, dfn[i]=0, du[i]=0, res[i]=0;
	for(int i=0;i<=n;++i) mark[i]=0, head[i]=0, G[i].clear();
	for(int i=1;i<=m;++i){
		a=read(), b=read();
		c=read(), d=read(); ind[i]=0;
		mark[a]=mark[c]=1;
		if(b+d==2) A.pb(i), ind[i]=1;
		if(b+d==3){
			if(d==1) swap(a,c);
			add(a,c,i);
		}
		if(b+d==4) add(0,a,0), add(0,c,0), B.pb(i), ind[i]=1;
	}
	int ans=0; mark[0]=1;
	for(int i=1;i<=n;++i) ans+=mark[i];
	for(int i=0;i<=n;++i){
		if(dfn[i] || !mark[i]) continue;
		tarjan(i);
	}
	for(int i=0;i<=n;++i)
		for(int j=head[i];j;j=ne[j]){
			if(bel[i]!=bel[to[j]]){
				node[bel[to[j]]]=to[j];
				G[bel[to[j]]].pb(mk(bel[i],weight[j]));  du[bel[i]]++; ind[weight[j]]=1; res[bel[to[j]]]++;
			}
		}
	hd=1, tl=0;
	for(int i=1;i<=colcnt;++i) if(du[i]==0) Q[++tl]=i; (ans<<=1);
	for(int i=1;i<=colcnt;++i) if(res[i]==0) ans--; ans++;
	eprint(ans); for(auto i:A) sprint(i);
	for(int i=1;i<=colcnt;++i) P[i].clear(), DFS(node[i]);
	for(int i=1;i<=m;++i) if(ind[i]==0) sprint(i);
	while(hd<=tl){
		int t=Q[hd++];
		for(auto i:P[t]) if(i) sprint(i);//强联通分量内部的边
		for(auto ver:G[t]){
			if(ver.se) sprint(ver.se);//不同强联通分量之间的边
			if((--du[ver.fi])==0) Q[++tl]=ver.fi;
		}
	}
	for(auto i:B) sprint(i); putchar(10);
}

signed main(){
	int t=read();
	while(t--) solve();
	return 0;
}





































































标签:Canvas,联通,P9697,题解,long,int,MAXN,分量,define
From: https://www.cnblogs.com/OccasionalDreamer/p/18012091

相关文章

  • P10013 Tree Topological Order Counting 题解
    首先题目里面写了每一个数都有权值,一般这种题只能去想求出每一个的具体方案数,那么也就是我们得求出\(h_{i,j}\)表示在所有合法拓扑序中\(a_i=j\)的方案数。一颗树的拓扑序数量是\(\dfrac{n!}{\prodsiz_i}\),相信大家都知道。因为我们需要保证这一棵树满足拓扑排序的条件,不......
  • P10068 [CCO2023] Line Town 题解
    好题,但是感觉写起来有点屎。题目大意给定一个序列\(a\),你每次可以选择\(i\in[1,n-1]\),交换\(a_i,a_{i+1}\),并且给\(a_i,a_{i+1}\)取相反数。问你最少需要多少次交换才能使得序列非降,可能无解。做法首先考虑给偶数位置初始乘上\(-1\),然后操作变成交换相邻两个数,下面提......
  • CF1706E 题解
    你谷题目传送门CF题目传送门题目大意给定一个\(n\)个点\(m\)条边的无向图,询问\(q\)次,每次询问会指定两个正整数\(l,r\),问要使对于\(l\leqa\leqb\leqr\)的所有\(a,b\)均有路径可以互相到达,最少需要加入前多少条边。思路考虑到每一次询问实质上就是问你在按......
  • [COCI2007-2008#1] ZAPIS 题解
    题目传送门前置知识区间型动态规划思考过程这题也算是一道很经典的问题了(?)。看见\(n\leq200\),不难想到复杂度为\(O(n^3)\)的区间型动态规划。题面中有这么一段话。空串是规则括号序列。如果\(\textttA\)是规则括号序列,那么\(\texttt{(A)[A]{A}}\)都是规则括号......
  • CF1735D Meta-set 题解
    题目大意给定\(n\)张卡牌,每张卡牌有\(k\)个属性,第\(i\)张卡牌的第\(j\)个属性为\(c_{i,j}\)。一个由\(3\)张卡牌\(x,y,z\)组成的集合被称作好的,当且仅当对于\(1\leqi\leqk\)均有\(c_{x,i}=c_{y,i}=c_{z,i}\)或者\(c_{x,i},c_{y,i},c_{z,i}\)两两不相等。......
  • CF1793E Velepin and Marketing 题解
    题目大意有\(n\)个读者,第\(i\)年他们要一起读\(k_i\)本书,每一本书至少要让一个人读,每一个人也只能读恰好一本书。如果某一个人\(j\),如果有\(a_j\)个人这一年里和他读了同一本书,那么他就会感到满足。对于所有的\(q\)组询问,每组给定一个\(k_i\),求感到满足的人数的最......
  • CF1735E House Planning 题解
    题目大意一条直线上有\(n\)个房子和两个人,房子的坐标\(d_1,d_2,d_3\dotsd_n\),以及两个人坐标为\(p_1,p_2\)。现在会告诉你两个集合\(S_1=\{|p_1-d_i|,1\leqi\leqn\}\)以及\(S_2=\{|p_2-d_i|,1\leqi\leqn\}\)。这个写法可能不是很规范,但为了美观就写成这样了。......
  • CF1847E Triangle Platinum? 题解
    感谢@swiftc管理反馈的信息,对于题目大意确定的东西进行了完善。交互题。题目大意有一个长度为\(n\)的序列\(a\)满足\(1\leqa_i\leq4\),现在你可以进行不超过\(5500\)次询问,每次询问询问三个数\(1\leqi<j<k\leqn\),你将会得到\(a_i,a_j,a_k\)构成的三角形......
  • [ABC327G] Many Good Tuple Problems 题解
    Description对于一对长度均为\(M\)且元素值在\(\left[1,N\right]\)之间的序列\((S,T)\),定义其为好的当且仅当:存在一个长度为\(N\)的\(01\)序列\(X\),使得其满足如下条件:对于任意\(i\in\left[1,M\right]\),有\(X_{S_i}\neqX_{T_i}\)。给定\(N,M\),求在......
  • CF1918G Permutation of Given 题解
    总体思路本题通过每次在已知序列中加入\(2\)个元素的方法,可以构造出满足条件的序列\(A\),这里提供一种新的构造方法。性质因为序列\(A\)中所有元素构成的可重集与序列\(B\)中所有元素构成的可重集完全相等,所以\(A\)中所有元素之和与\(B\)中所有元素之和相等。\[\s......