百折不挠|

Xdik

园龄:1个月粉丝:7关注:24

CF1635E Cars

题意

n 辆车,每个车有一个运行的方向(L 表示向左走,R 表示向右走)和初始位置,速度为任意值,这些都是不知道的,需要我们去求,已知的是 m 个关系 。

1 i j 表示第 i 辆车和第 j 辆车必定不会相遇。

2 i j 表示第 i 辆车和第 j 辆车必定会相遇。

Solution

考虑在何种情况下两辆车必定不会相遇,因为速度任意,所以两辆车不能是同一个方向,因为这样可能会发生追及,所以方向只能是一个向左一个向右,然后很容易就能得出向左走的那辆车必须在向右走的那辆车的左边。再考虑何种情况一定会发生相遇,发现与上一种情况一样,不能是同向的,因为这样不一定会发生追及,所以这两辆车的方向还是不一样,与上一种情况的区别就是向左走的那辆车必须在向右走的那辆车的右边,那么现在我们就发现有关系的两辆车它们的方向一定是不一样的,又因为只有 L 和 R 两种情况,所以很容易想到了二分图,于是我们用二分图染色跑一遍,如果出现了奇环就说明无解,现在我们得到了每辆车的方向之后就只用解决它们的位置。为要处理大小关系,所以一开始我的想法是差分约束系统,但是发现时间复杂度不正确。因为我们只用处理某个数比某个数小或者比某个数大的情况,所以可以用拓扑排序来解决。如果 ai<aj 那么我们就从 ij 连一条边,再来跑拓扑排序,最后得到的拓扑序肯定是一个合法的 a 序列。为什么这样是对的呢?因为我们跑拓扑是按照入度为 0 才入队的,因为 ij 连了一条边,所以肯定是 i 出队了 j 才可能入队,所以就满足了 ai<aj 的条件。

因为二分图的时间复杂度为 O(n) 拓扑排序的时间复杂度也为 O(n) 所以总的时间复杂度也是 O(n)

这道题结合了二分图和拓扑排序,还是挺有价值的。

AC code:

#include<bits/stdc++.h>
#define int long long
#pragma GCC optimeze(2)
#pragma GCC optimeze(3)
#define lowbit(x) (x&(-x))
#define fi first	
#define PII pair<int,int> 
#define se second 
#define pu(x) push_back(x)
using namespace std;
const int N=2e5+5;
int read() {
	int x=0,flag=1;
	char ch=0;
	while(ch<'0'||ch>'9') {
		if(ch=='-')flag=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=(x<<1)+(x<<3)+ch-'0';
		ch=getchar();
	}
	return flag*x;
}
void write(int x) {
  if(x<0)putchar('-'),x=-x; 
  static int sta[35];
  int top = 0;
  do {
    sta[top++] = x % 10, x /= 10;
  } while (x);
  while (top) putchar(sta[--top] + 48);
}
int n,m,in[N],ans[N],c[N],head[N],ver[N*2],ne[N*2],op[N],u[N],v[N],tot,cnt;
vector<int>G[N];
void add(int x,int y){
	ver[++tot]=y,ne[tot]=head[x],head[x]=tot;
}
void dfs(int t,int co){
	c[t]=co;
	for(int i=head[t];i;i=ne[i]){
		int to=ver[i];
		if(c[to]){
			if(c[to]==c[t]){
				cout<<"NO";
				exit(0);
			}
		}
		else dfs(to,3-co);
	}
}
signed main() {
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		op[i]=read(),u[i]=read(),v[i]=read();
		add(u[i],v[i]),add(v[i],u[i]);
	}
	for(int i=1;i<=n;i++){
		if(!c[i])dfs(i,1);
	}
	for(int i=1;i<=m;i++){
		if(op[i]==1){
			if(c[u[i]]==1)G[u[i]].push_back(v[i]),in[v[i]]++;
			else G[v[i]].push_back(u[i]),in[u[i]]++;
		}
		else{
			if(c[u[i]]==2)G[u[i]].push_back(v[i]),in[v[i]]++;
			else G[v[i]].push_back(u[i]),in[u[i]]++;
		}
	}
	queue<int>q;
	for(int i=1;i<=n;i++){
		if(!in[i])q.push(i);
	
	while(q.size()){
		int t=q.front();
		q.pop();
		ans[t]=++cnt;
		for(auto to:G[t]){
			in[to]--;
			if(!in[to])q.push(to);
		}
	}
	if(cnt<n){
		cout<<"NO";
	}
	else{
		puts("YES");
		for(int i=1;i<=n;i++){
			cout<<(c[i]==1? 'L':'R')<<" "<<ans[i]<<endl;
		}
	}
	return 0;
}

本文作者:Xdik

本文链接:https://www.cnblogs.com/Xdik/p/18708132

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Xdik  阅读(3)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起