题解 中学生物理题
喵的欧拉回路的题我从来做不出来
一个暴力是离散化后从每个点开始暴力找循环
让每条边只被经过一次就可以做到 \(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;
}