E - Cars
分析:
-
二分图染色,拓扑排序
-
分两类情况:
相遇:只能相向而行( x r < x l x_r<x_l xr<xl)
相离:只能背向而行( x r > x l x_r>x_l xr>xl)
因此,不管是什么情况,相邻两点方向不同,先跑一遍二分图染色,不成立,则 “NO”
-
染完色之后,令 1向R走,0向L走,建有向图
相遇: x r < x l x_r<x_l xr<xl ,建 1 到 0 的边
相离: x r > x l x_r>x_l xr>xl ,建 0 到 1 的边
建完图,跑一边拓扑排序,即 ans
-
注意:有可能建的图不能够完全跑完,输出 “NO”
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
struct node
{
int t,u,v;
}e[N];
vector <int> g[N],g2[N];
int vis[N], clr[N];
bool dfs(int u,int tag)
{
vis[u]=1; clr[u]=tag;
for(int v : g[u])
{
if(vis[v] && clr[v]==tag) return false;
if(!vis[v]) dfs(v,tag^1);
}
return true;
}
int in[N], ans[N], tot;
void topsort(int n)
{
queue <int> q;
for(int i=1;i<=n;i++) if(!in[i]) q.push(i);
while(!q.empty())
{
int u=q.front(); q.pop();
ans[u]=++tot;
for(int v : g2[u])
{
in[v]--;
if(!in[v]) q.push(v);
}
}
}
void solve()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&e[i].t,&e[i].u,&e[i].v);
g[e[i].u].push_back(e[i].v);
g[e[i].v].push_back(e[i].u);
}
int fg=0;
memset(clr,-1,sizeof(clr));
for(int i=1;i<=n;i++)
{
if(!vis[i] && !dfs(i,1))
{
fg=1; break;
}
}
if(fg) puts("NO");
else
{
for(int i=1;i<=m;i++)
{
if(clr[e[i].u] && e[i].t==2 || !clr[e[i].u] && e[i].t==1)
{
g2[e[i].u].push_back(e[i].v);
in[e[i].v]++;
}
else g2[e[i].v].push_back(e[i].u), in[e[i].u]++;
}
topsort(n);
if(tot!=n) puts("NO"); //不完全跑完
else
{
puts("YES");
for(int i=1;i<=n;i++)
{
if(clr[i]) cout<<"R "<<ans[i]<<"\n";
else cout<<"L "<<ans[i]<<"\n";
}
}
}
}
signed main()
{
int T=1;
//cin>>T;
while(T--) solve();
}