首页 > 其他分享 >[POI2011] SMI-Garbage 题解

[POI2011] SMI-Garbage 题解

时间:2023-11-10 21:33:34浏览次数:31  
标签:Garbage int 题解 POI2011 nd st 偶数 fa find

题目链接

显然,对于初始颜色与目标颜色不同的边,我们需要走过奇数次;对于初始颜色与目标颜色相同的边,我们需要走过偶数次。

对于只有偶数边的情况,这种情况下不走就行;对于只有奇数边;可以理解为每条边只能经过一次,就是欧拉路径问题,并且考虑这题的特殊性质,如果一个图是由若干个简单环构成的连通图,那么显然每个点度数为偶数,毕竟环都是进一次出一次。所以在判断方面,只需判断偶数边即可。

那么我们考虑将两种情况合起来,可以发现,如果只有奇数边情况无解,那么加几个偶数边也无济于事,所以对于偶数边,就不用加了,只加奇数边,那么一定会形成若干连通块,分别对每个连通块进行考虑即可。

对于一个连通块,先求出其欧拉路径,然后用类似 tarjan 的方法,设置一个栈,一旦遇到与当前栈的元素重复就加进新的答案。具体看代码。

有一说一,原来用的 \(vector+map\) 做,超时,但是用邻接表做则可以AC,果然常数还是太大了。

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
#define PII pair<int,int>
inline LL read() {
	LL sum=0,flag=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') flag=-1; c=getchar();}
	while(c>='0'&&c<='9') {sum=sum*10+c-'0'; c=getchar();}
	return sum*flag;
}

const int N=1e5+10,M=2e6+10;
int n,m,ans_cnt;
int fa[N],vis[N];
int del[N],deg[N];
vector<int> id[N],ans[N];
stack<int> st;
int f[M],tot=1,h[N],to[M],nxt[M];

void add(int x,int y) {
	to[++tot]=y; nxt[tot]=h[x]; h[x]=tot;
}

int find(int x) {
	if(x==fa[x]) return x;
	else return fa[x]=find(fa[x]);
}

void merge(int x,int y) {
	int fx=find(x),fy=find(y);
	if(fx!=fy) fa[fx]=fy;
}

void dfs(int nd) {
	for(int i=h[nd];i;i=nxt[i]) {
		if(f[i]) continue;
		int x=to[i];
		f[i]=f[i^1]=1;
		h[nd]=nxt[i];
		dfs(x);
	}
	st.push(nd);
}

int main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=m;i++) {
		int a=read(),b=read(),s=read(),t=read();
		if(s!=t) {
			add(a,b); add(b,a);
			deg[a]++; deg[b]++;
			merge(a,b);
		}
	}
	for(int i=1;i<=n;i++) {
		id[find(i)].push_back(i);
	}
	for(int i=1;i<=n;i++) {
		if(fa[i]==i) {
			int cnt=0,sz=id[i].size();
			for(int x:id[i]) {
				if(deg[x]%2==0) cnt++;
			}
			if(cnt==sz) {
				dfs(id[i][0]);
				stack<int> stk;
				while(st.size()) {
					int x=st.top(); st.pop();
					if(vis[x]) {
						++ans_cnt; int y=0;
						do {
							y=stk.top();
							ans[ans_cnt].push_back(y);
							vis[y]=0; stk.pop();							
						}while(y!=x);
					}
					stk.push(x); vis[x]=1;
				}
			}
			else {
				cout<<"NIE"; return 0;
			}
		}
	}
	cout<<ans_cnt<<endl;
	for(int i=1;i<=ans_cnt;i++) {
		cout<<ans[i].size()<<" ";
		for(int x:ans[i]) cout<<x<<" ";
		cout<<ans[i][0]<<"\n";
	}
	return 0;
}

标签:Garbage,int,题解,POI2011,nd,st,偶数,fa,find
From: https://www.cnblogs.com/zhangyuzhe/p/17825115.html

相关文章

  • CSP-S2019 江西 题解
    为什么有\(5\)道题?[CSP-S2019江西]和积和简单化一下式子:\[(n+1)\times\sumA_i\timesB_i-(\sumA_i)\times(\sumB_i)\]其中\(A,B\)都是前缀和。[CSP-S2019江西]网格图naive的kruskal是很naive的,所以需要一点简单的优化。考虑其本质过程就是按照......
  • CF1485E Move and Swap 题解
    不要什么脑子的带\(log\)做法。思路考虑\(dp_{i,j}\)表示红点到\(i\),蓝点到\(j\)的最大权值。那么有:\[dp_{i,j}=\max(dp_{fa_i,pre},dp_{fa_j,pre})+|a_i-a_j|\]其中\(pre\)是任意一个上一层节点。发现第二维没有用。可以优化:\[dp_i=\max(dp_{fa_i}+\max(|a_i-a_......
  • APISIX源码安装问题解决
    官网手册的安装语句:curlhttps://raw.githubusercontent.com/apache/apisix/master/utils/install-dependencies.sh-sL|bash-执行install-dependencies.sh报如下错误:Transactioncheckerror:file/usr/share/gcc-4.8.2/python/libstdcxx/v6/printers.pyfrominstal......
  • 苏格拉底问答、实践过程截图、遇到问题解决问题截图,代码链接
    #include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<signal.h>#include<setjmp.h> //foralongjumpjmp_bufenv;//forsavinglonjmpenviromentintcount=0;voidhandler(intsig,......
  • CSP-2019-S 题解
    做了这套题,如果是让现在的我当时去考的话应该一共可以有450分,格雷码,括号树,树的重心都可以做,树上的数可以有10分,Emiya至少可以有76分,划分也可以有64分。看OIerDB上可以有166名的好成绩。我的代码合集:洛谷/云剪贴板[CSP-S2019]格雷码首先是格雷码有一个很好的生......
  • CF1428F Fruit Sequences 题解
    使用了一种和大多数题解不同的做法。虽然是带\(log\)的。思路首先考虑如何求一个固定左端点的答案。我们发现,每个答案会随着右端点的递增单调不降。而每个答案在增加时会形成若干个区间。例如:11101010111111我们答案增加的区间即为:11100000000111可以发现,这个区间就......
  • 【洛谷 P1980】[NOIP2013 普及组] 计数问题 题解(取余)
    [NOIP2013普及组]计数问题题目描述试计算在区间到的所有整数中,数字()共出现了多少次?例如,在到中,即在中,数字出现了次。输入格式个整数,之间用一个空格隔开。输出格式个整数,表示出现的次数。样例#1样例输入#1111样例输出#14提示对于的数据,,。思路求每个数字的......
  • [ABC286G] Unique Walk 题解
    洛谷题目链接At题目链接这题一看就很欧拉路径,但是怎么做呢?如果只有关键边,那么连通图首先会变成一堆连通块,这时只需要分别对每个连通块进行欧拉路径判断,但是对于不属于欧拉路径的连通块,很难对加上非关键边的情况进行扩展。如果只有非关键边,那么连通图还是变成一堆连通块,但是这......
  • 题解 P4630 [APIO2018] 铁人两项
    具体思路题目问的是三元组\((x,z,y)\)使得\(x\)可以到达\(z\),且\(z\)可以到达\(y\),求三元组\((x,z,y)\)的数量。我们转化一下问题,就是问\(x,y\)之间所有不重复路径的点的并集减\(2\)。显然,无向图中任意一个点都属于一个点双连通分量。那么问题转化为\(x,y\)之......
  • [题解] P6773 [NOI2020] 命运
    P6773[NOI2020]命运给你一棵\(n\)个节点的树,要给每条边染成\(0\)或\(1\)。有\(m\)个限制\((u,v)\)满足\(u\)是\(v\)祖先,表示\(u\)到\(v\)的路径中至少有一条边被染成了1。求方案数。\(n,m\le5\times10^5\)。首先会想到容斥,但是很没前途,所以考虑......