题解 中学生物理题

传送门

喵的欧拉回路的题我从来做不出来

一个暴力是离散化后从每个点开始暴力找循环
让每条边只被经过一次就可以做到 \(O(n)\) 找环
然后只有一个循环的可以直接构造
\(n\leqslant 40\) 的可以卡时+剪枝大力搜

然后正解:
还是先找出循环
然后把循环看成点,镜子看成边,无穷远建成虚点
现在要给边染色使对于每个点,与其相连的每种颜色的边数量都相等且为偶数
那么显然有个条件是每个点的度数都是 8 的倍数
然后怎么构造方案呢?
一个神仙思路是欧拉回路
虚点开始跑个欧拉回路,将经过的边按照经过次序的奇偶分成两组
这样分后只考虑一组的边,每个点的度数一定是 4 的倍数
那么只保留一组中的边重复上述过程
可以分出 4 组边,将每组染成同种颜色即可
将一组分为两组的过程的原理是一组出入边的颜色不同
有自环不会产生影响,此时是一组同色出入边和自环颜色不同
复杂度 \(O(n\log n)\),瓶颈在排序和离散化

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long

int n;
int x[N], y[N];
char c[N], s[10];

namespace force{
	#undef unix
	#define left 0
	#define down 1
	#define right 2
	#define up 3
	vector<int> loop;
	bool vis[N][2], isloop[N];
	vector<pair<int, int>> ln[N], col[N];
	int bel[N][2], siz[N], ans[N], need[10];
	int unix[N], uniy[N], idx[N], idy[N], xsiz, ysiz, tot;
	inline int go_left(int now) {
		if (!idx[now]) return -1;
		else return ln[y[now]][idx[now]-1].sec;
	}
	inline int go_right(int now) {
		if (idx[now]+1==ln[y[now]].size()) return -1;
		else return ln[y[now]][idx[now]+1].sec;
	}
	inline int go_down(int now) {
		if (!idy[now]) return -1;
		else return col[x[now]][idy[now]-1].sec;
	}
	inline int go_up(int now) {
		if (idy[now]+1==col[x[now]].size()) return -1;
		else return col[x[now]][idy[now]+1].sec;
	}
	bool dfs(int now, int side, int tr, int id) {
		// cout<<"dfs: "<<now<<' '<<side<<' '<<tr<<' '<<id<<endl;
		while (1) {
			// cout<<"now: "<<x[now]<<' '<<y[now]<<' '<<side<<' '<<tr<<endl;
			if (vis[now][side]) return 1;
			vis[now][side]=1;
			++siz[bel[now][side]=id];
			int lst=now;
			if (!side) {
				if (tr==left) now=go_up(now), tr=up, side^=1;
				else if (tr==down&&c[now]=='/') now=go_left(now), tr=left, side^=(c[lst]==c[now]);
				else if (tr==down&&c[now]=='\\') now=go_right(now), tr=right, side^=(c[lst]==c[now]);
				else if (tr==right) now=go_up(now), tr=up, side^=1;
				else assert(0);
				if (now==-1) return 0;
			}
			else {
				if (tr==left) now=go_down(now), tr=down, side^=1;
				else if (tr==up&&c[now]=='/') now=go_right(now), tr=right, side^=(c[lst]==c[now]);
				else if (tr==up&&c[now]=='\\') now=go_left(now), tr=left, side^=(c[lst]==c[now]);
				else if (tr==right) now=go_down(now), tr=down, side^=1;
				else assert(0);
				if (now==-1) return 0;
			}
		}
	}
	void disable(int now, int side, int tr) {
		while (1) {
			assert(vis[now][side]);
			bel[now][side]=-1;
			int lst=now;
			if (!side) {
				if (tr==left) now=go_up(now), tr=up, side^=1;
				else if (tr==down&&c[now]=='/') now=go_left(now), tr=left, side^=(c[lst]==c[now]);
				else if (tr==down&&c[now]=='\\') now=go_right(now), tr=right, side^=(c[lst]==c[now]);
				else if (tr==right) now=go_up(now), tr=up, side^=1;
				else assert(0);
				if (now==-1) return ;
			}
			else {
				if (tr==left) now=go_down(now), tr=down, side^=1;
				else if (tr==up&&c[now]=='/') now=go_right(now), tr=right, side^=(c[lst]==c[now]);
				else if (tr==up&&c[now]=='\\') now=go_left(now), tr=left, side^=(c[lst]==c[now]);
				else if (tr==right) now=go_down(now), tr=down, side^=1;
				else assert(0);
				if (now==-1) return ;
			}
		}
	}
	void solve() {
		for (int i=1; i<=n; ++i) unix[++xsiz]=x[i];
		for (int i=1; i<=n; ++i) uniy[++ysiz]=y[i];
		sort(unix+1, unix+xsiz+1);
		sort(uniy+1, uniy+ysiz+1);
		xsiz=unique(unix+1, unix+xsiz+1)-unix;
		ysiz=unique(uniy+1, uniy+ysiz+1)-uniy;
		for (int i=1; i<=n; ++i) x[i]=lower_bound(unix+1, unix+xsiz+1, x[i])-unix;
		for (int i=1; i<=n; ++i) y[i]=lower_bound(uniy+1, uniy+ysiz+1, y[i])-uniy;
		for (int i=1; i<=n; ++i) ln[y[i]].pb({x[i], i}), col[x[i]].pb({y[i], i});
		for (int i=1; i<=ysiz; ++i) sort(ln[i].begin(), ln[i].end());
		for (int i=1; i<=xsiz; ++i) sort(col[i].begin(), col[i].end());
		for (int i=1; i<=ysiz; ++i) for (int j=0; j<ln[i].size(); ++j) idx[ln[i][j].sec]=j;
		for (int i=1; i<=xsiz; ++i) for (int j=0; j<col[i].size(); ++j) idy[col[i][j].sec]=j;
		for (int i=1; i<=n; ++i) {
			if (!vis[i][0]) {
				siz[++tot]=0;
				if (!dfs(i, 0, down, tot)) {
					--tot;
					disable(i, 0, down);
					if (c[i]=='/') disable(i, 0, right);
					else disable(i, 0, left);
				}
			}
			if (!vis[i][1]) {
				siz[++tot]=0;
				if (!dfs(i, 1, up, tot)) {
					--tot;
					disable(i, 1, up);
					if (c[i]=='/') disable(i, 1, left);
					else disable(i, 1, right);
				}
			}
		}
		// cout<<"tot: "<<tot<<endl;
		// cout<<"siz: "; for (int i=1; i<=tot; ++i) cout<<siz[i]<<' '; cout<<endl;
		for (int i=1; i<=tot; ++i) if (siz[i]%8) {puts("-1"); exit(0);}
		// assert(tot==1);
		for (int i=1; i<=4; ++i) need[i]=siz[1]/4;
		for (int i=1; i<=n; ++i)
			if (~bel[i][0]&&~bel[i][1]) {
				// cout<<"both: "<<x[i]<<' '<<y[i]<<endl;
				for (int j=1; j<=4; ++j) if (need[j]>=2) {
					need[j]-=2;
					ans[i]=j;
					break;
				}
				if (!ans[i]) {puts("-1"); exit(0);}
			}
		for (int i=1; i<=n; ++i) if (!ans[i]) {
			if (bel[i][0]==-1&&bel[i][1]==-1) ans[i]=1;
			else {
				for (int j=1; j<=4; ++j) if (need[j]) {
					--need[j];
					ans[i]=j;
					break;
				}
			}
		}
		for (int i=1; i<=n; ++i) printf("%d%c", ans[i], " \n"[i==n]);
	}
}

namespace task1{
	#undef unix
	#define left 0
	#define down 1
	#define right 2
	#define up 3
	vector<int> loop;
	int sta[N], tem[N], top;
	bool vis[N][2], isloop[N];
	vector<pair<int, int>> ln[N], col[N];
	int bel[N][2], siz[N], ans[N], need[10], cnt[N][5];
	int unix[N], uniy[N], idx[N], idy[N], xsiz, ysiz, tot;
	inline int go_left(int now) {
		if (!idx[now]) return -1;
		else return ln[y[now]][idx[now]-1].sec;
	}
	inline int go_right(int now) {
		if (idx[now]+1==ln[y[now]].size()) return -1;
		else return ln[y[now]][idx[now]+1].sec;
	}
	inline int go_down(int now) {
		if (!idy[now]) return -1;
		else return col[x[now]][idy[now]-1].sec;
	}
	inline int go_up(int now) {
		if (idy[now]+1==col[x[now]].size()) return -1;
		else return col[x[now]][idy[now]+1].sec;
	}
	bool dfs(int now, int side, int tr, int id) {
		// cout<<"dfs: "<<now<<' '<<side<<' '<<tr<<' '<<id<<endl;
		while (1) {
			// cout<<"now: "<<x[now]<<' '<<y[now]<<' '<<side<<' '<<tr<<endl;
			if (vis[now][side]) return 1;
			vis[now][side]=1;
			++siz[bel[now][side]=id];
			int lst=now;
			if (!side) {
				if (tr==left) now=go_up(now), tr=up, side^=1;
				else if (tr==down&&c[now]=='/') now=go_left(now), tr=left, side^=(c[lst]==c[now]);
				else if (tr==down&&c[now]=='\\') now=go_right(now), tr=right, side^=(c[lst]==c[now]);
				else if (tr==right) now=go_up(now), tr=up, side^=1;
				else assert(0);
				if (now==-1) return 0;
			}
			else {
				if (tr==left) now=go_down(now), tr=down, side^=1;
				else if (tr==up&&c[now]=='/') now=go_right(now), tr=right, side^=(c[lst]==c[now]);
				else if (tr==up&&c[now]=='\\') now=go_left(now), tr=left, side^=(c[lst]==c[now]);
				else if (tr==right) now=go_down(now), tr=down, side^=1;
				else assert(0);
				if (now==-1) return 0;
			}
		}
	}
	void disable(int now, int side, int tr) {
		while (1) {
			assert(vis[now][side]);
			bel[now][side]=-1;
			int lst=now;
			if (!side) {
				if (tr==left) now=go_up(now), tr=up, side^=1;
				else if (tr==down&&c[now]=='/') now=go_left(now), tr=left, side^=(c[lst]==c[now]);
				else if (tr==down&&c[now]=='\\') now=go_right(now), tr=right, side^=(c[lst]==c[now]);
				else if (tr==right) now=go_up(now), tr=up, side^=1;
				else assert(0);
				if (now==-1) return ;
			}
			else {
				if (tr==left) now=go_down(now), tr=down, side^=1;
				else if (tr==up&&c[now]=='/') now=go_right(now), tr=right, side^=(c[lst]==c[now]);
				else if (tr==up&&c[now]=='\\') now=go_left(now), tr=left, side^=(c[lst]==c[now]);
				else if (tr==right) now=go_down(now), tr=down, side^=1;
				else assert(0);
				if (now==-1) return ;
			}
		}
	}
	void solve() {
		for (int i=1; i<=n; ++i) unix[++xsiz]=x[i];
		for (int i=1; i<=n; ++i) uniy[++ysiz]=y[i];
		sort(unix+1, unix+xsiz+1);
		sort(uniy+1, uniy+ysiz+1);
		xsiz=unique(unix+1, unix+xsiz+1)-unix;
		ysiz=unique(uniy+1, uniy+ysiz+1)-uniy;
		for (int i=1; i<=n; ++i) x[i]=lower_bound(unix+1, unix+xsiz+1, x[i])-unix;
		for (int i=1; i<=n; ++i) y[i]=lower_bound(uniy+1, uniy+ysiz+1, y[i])-uniy;
		for (int i=1; i<=n; ++i) ln[y[i]].pb({x[i], i}), col[x[i]].pb({y[i], i});
		for (int i=1; i<=ysiz; ++i) sort(ln[i].begin(), ln[i].end());
		for (int i=1; i<=xsiz; ++i) sort(col[i].begin(), col[i].end());
		for (int i=1; i<=ysiz; ++i) for (int j=0; j<ln[i].size(); ++j) idx[ln[i][j].sec]=j;
		for (int i=1; i<=xsiz; ++i) for (int j=0; j<col[i].size(); ++j) idy[col[i][j].sec]=j;
		for (int i=1; i<=n; ++i) {
			if (!vis[i][0]) {
				siz[++tot]=0;
				if (!dfs(i, 0, down, tot)) {
					--tot;
					disable(i, 0, down);
					if (c[i]=='/') disable(i, 0, right);
					else disable(i, 0, left);
				}
			}
			if (!vis[i][1]) {
				siz[++tot]=0;
				if (!dfs(i, 1, up, tot)) {
					--tot;
					disable(i, 1, up);
					if (c[i]=='/') disable(i, 1, left);
					else disable(i, 1, right);
				}
			}
		}
		// cout<<"tot: "<<tot<<endl;
		// cout<<"siz: "; for (int i=1; i<=tot; ++i) cout<<siz[i]<<' '; cout<<endl;
		for (int i=1; i<=tot; ++i) if (siz[i]%8) {puts("-1"); exit(0);}
		for (int i=1; i<=n; ++i) if (~bel[i][0]&&~bel[i][1]) sta[top++]=i; //, cout<<i<<endl;
		int lim=1<<(top<<1);
		for (int s=0; s<lim; ++s) {
			for (int i=1; i<=tot; ++i) for (int j=0; j<4; ++j) cnt[i][j]=0;
			for (int i=0; i<top; ++i) tem[i]=(s>>(i<<1))&3;
			for (int i=0; i<top; ++i) {
				++cnt[bel[sta[i]][0]][tem[i]];
				++cnt[bel[sta[i]][1]][tem[i]];
			}
			for (int i=1; i<=tot; ++i) for (int j=0; j<4; ++j) if (cnt[i][j]>siz[i]/4) goto jump;
			for (int i=1; i<=tot; ++i) for (int j=0; j<4; ++j) cnt[i][j]=siz[i]/4-cnt[i][j];
			for (int i=0; i<top; ++i) ans[sta[i]]=tem[i]+1;
			for (int i=1; i<=n; ++i) if (!ans[i]) {
				if (bel[i][0]==-1&&bel[i][1]==-1) ans[i]=1;
				else {
					int id=bel[i][0]==-1?bel[i][1]:bel[i][0];
					for (int j=0; j<4; ++j) if (cnt[id][j]) {
						--cnt[id][j];
						ans[i]=j+1;
						break;
					}
				}
			}
			for (int i=1; i<=n; ++i) printf("%d%c", ans[i], " \n"[i==n]);
			exit(0);
			jump: ;
		}
		puts("-1");
	}
}

namespace task{
	bool vis[N], tag[N];
	struct edge{int from, to, next;}e[N<<1];
	vector<pair<int, int>> ln[N], col[N];
	int head[N], dsu[N], id[N], cur[N], ans[N], ecnt=1;
	int unix[N], uniy[N], idx[N], idy[N], sta[N], siz[N], xsiz, ysiz, tot, top;
	inline void add(int s, int t) {e[++ecnt]={s, t, head[s]}; head[s]=ecnt;}
	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
	inline void link(int s, int t) {
		int ids=s, idt=t;
		if (s>t) swap(s, t);
		if (s==-1) s=find(1);
		if ((s=find(s))!=(t=find(t)))
			siz[dsu[s]=t]+=siz[s]; //, cout<<"link: "<<x[ids>>1]<<' '<<y[ids>>1]<<' '<<(ids&1)<<", "<<x[idt>>1]<<' '<<y[idt>>1]<<' '<<(idt&1)<<endl;
	}
	inline int go_left(int now) {
		if (!idx[now]) return -1;
		else return ln[y[now]][idx[now]-1].sec;
	}
	inline int go_right(int now) {
		if (idx[now]+1==ln[y[now]].size()) return -1;
		else return ln[y[now]][idx[now]+1].sec;
	}
	inline int go_down(int now) {
		if (!idy[now]) return -1;
		else return col[x[now]][idy[now]-1].sec;
	}
	inline int go_up(int now) {
		if (idy[now]+1==col[x[now]].size()) return -1;
		else return col[x[now]][idy[now]+1].sec;
	}
	inline int in_left(int now) {
		if (now==-1) return -1;
		else return c[now]=='/'?(now<<1|1):(now<<1);
	}
	inline int in_right(int now) {
		if (now==-1) return -1;
		else return c[now]=='/'?(now<<1):(now<<1|1);
	}
	inline int in_down(int now) {
		if (now==-1) return -1;
		else return now<<1;
	}
	inline int in_up(int now) {
		if (now==-1) return -1;
		else return now<<1|1;
	}
	void dfs1(int u) {
		// cout<<"dfs1: "<<u<<endl;
		while (~cur[u]) {
			int i=cur[u];
			cur[u]=e[cur[u]].next;
			if (!vis[i>>1]) {
				vis[i>>1]=1;
				dfs1(e[i].to);
				if ((++top)&1) tag[i>>1]=1;
				// cout<<"("<<e[i].from<<','<<e[i].to<<") "; cout<<endl;
			}
		}
	}
	void dfs2(int u) {
		// cout<<"dfs1: "<<u<<endl;
		while (~cur[u]) {
			int i=cur[u];
			cur[u]=e[cur[u]].next;
			if (tag[i>>1]&&!vis[i>>1]) {
				vis[i>>1]=1;
				dfs2(e[i].to);
				if ((++top&1)) ans[i>>1]=1;
				else ans[i>>1]=2;
			}
		}
	}
	void dfs3(int u) {
		// cout<<"dfs3: "<<u<<endl;
		while (~cur[u]) {
			int i=cur[u];
			cur[u]=e[cur[u]].next;
			if (!tag[i>>1]&&!vis[i>>1]) {
				vis[i>>1]=1;
				dfs3(e[i].to);
				if ((++top)&1) ans[i>>1]=3;
				else ans[i>>1]=4;
			}
		}
	}
	void solve() {
		memset(head, -1, sizeof(head));
		for (int i=1; i<=n; ++i) unix[++xsiz]=x[i];
		for (int i=1; i<=n; ++i) uniy[++ysiz]=y[i];
		sort(unix+1, unix+xsiz+1);
		sort(uniy+1, uniy+ysiz+1);
		xsiz=unique(unix+1, unix+xsiz+1)-unix-1;
		ysiz=unique(uniy+1, uniy+ysiz+1)-uniy-1;
		for (int i=1; i<=n; ++i) x[i]=lower_bound(unix+1, unix+xsiz+1, x[i])-unix;
		for (int i=1; i<=n; ++i) y[i]=lower_bound(uniy+1, uniy+ysiz+1, y[i])-uniy;
		for (int i=1; i<=n; ++i) ln[y[i]].pb({x[i], i}), col[x[i]].pb({y[i], i});
		for (int i=1; i<=ysiz; ++i) sort(ln[i].begin(), ln[i].end());
		for (int i=1; i<=xsiz; ++i) sort(col[i].begin(), col[i].end());
		for (int i=1; i<=ysiz; ++i) for (int j=0; j<ln[i].size(); ++j) idx[ln[i][j].sec]=j;
		for (int i=1; i<=xsiz; ++i) for (int j=0; j<col[i].size(); ++j) idy[col[i][j].sec]=j;
		for (int i=1; i<=(n<<1|1); ++i) dsu[i]=i, siz[i]=1;
		for (int i=1; i<=n; ++i) {
			// cout<<"i: "<<x[i]<<' '<<y[i]<<endl;
			link(i<<1, in_up(go_up(i)));
			// cout<<"up: "<<x[go_up(i)]<<' '<<y[go_up(i)]<<' '<<go_up(i)<<endl;
			if (c[i]=='/') link(i<<1, in_left(go_left(i)));
			else link(i<<1, in_right(go_right(i)));
			link(i<<1|1, in_down(go_down(i)));
			if (c[i]=='/') link(i<<1|1, in_right(go_right(i)));
			else link(i<<1|1, in_left(go_left(i)));
		}
		for (int i=1; i<=(n<<1|1); ++i) if (i==find(i)) {
			id[i]=++tot;
			// cout<<siz[i]<<endl;
			if (i!=find(1) && siz[i]%8) {puts("-1"); exit(0);}
		}
		// cout<<"tot: "<<tot<<endl;
		// cout<<"bel: "; for (int i=1; i<=n; ++i) cout<<"("<<id[find(i<<1)]<<','<<id[find(i<<1|1)]<<") "; cout<<endl;
		for (int i=1; i<=n; ++i) add(id[find(i<<1)], id[find(i<<1|1)]), add(id[find(i<<1|1)], id[find(i<<1)]);
		for (int i=1; i<=tot; ++i) cur[i]=head[i]; dfs1(id[find(1)]);
		for (int i=1; i<=tot; ++i) dfs1(i);
		// cout<<"tag: "; for (int i=1; i<=n; ++i) cout<<tag[i]<<' '; cout<<endl;
		for (int i=1; i<=n; ++i) vis[i]=0;
		for (int i=1; i<=tot; ++i) cur[i]=head[i]; top=0; dfs2(id[find(1)]);
		for (int i=1; i<=tot; ++i) dfs2(i);
		for (int i=1; i<=n; ++i) vis[i]=0;
		for (int i=1; i<=tot; ++i) cur[i]=head[i]; top=0; dfs3(id[find(1)]);
		for (int i=1; i<=tot; ++i) dfs3(i);
		// for (int i=1; i<=top; i+=2) vis[sta[i]]=1; //ans[sta[i]]=1, cout<<sta[i]<<' '; cout<<endl;
		// cout<<"e: "; for (int i=2; i<=ecnt; i+=2) cout<<ans[i>>1]<<' '; cout<<endl;
		for (int i=2; i<=ecnt; i+=2) printf("%d%c", ans[i>>1], " \n"[i+1==ecnt]);
		// cout<<tot-1<<endl;
	}
}

signed main()
{
	freopen("scisyhp.in", "r", stdin);
	freopen("scisyhp.out", "w", stdout);

	scanf("%d", &n);
	for (int i=1; i<=n; ++i) scanf("%d%d%s", &x[i], &y[i], s), c[i]=*s;
	// if (n<=40) task1::solve();
	// else force::solve();
	task::solve();

	return 0;
}
posted @ 2022-06-19 15:26  Administrator-09  阅读(1)  评论(0编辑  收藏  举报