P14978 [USACO26JAN1] Mooclear Reactor S题解

USACO26JAN1 Mooclear Reactor S

思路

将限制建双向边,设一个联通块的根为 r t rt rt,则每个 a i a_i ai 一定可以表示为 a i = k × a r t + b a_i=k\times a_{rt}+b ai=k×art+b,其中 k ∈ { − 1 , 1 } k\in \left \{ -1,1 \right \} k∈{−1,1}。如果有环,那么每个 a i a_i ai 的值就确定了,检查一下有多少 a i a_i ai 产生动力即可。否则我们解出满足 l i ≤ a i ≤ r i l_i\le a_i \le r_i li≤ai≤ri 的 a r t a_{rt} art 取值范围。现在问题转换为:有若干线段,求一个点使包含这个点的线段数量最多。扫描线即可,时间复杂度 O ( n log ⁡ n ) O(n\log_{}{n}) O(nlogn),瓶颈在于排序。

代码

压行导致代码有点猎奇。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int t,n,m,cnt,l[N],r[N],tp[N],k[N],to[N<<1],nxt[N<<1],w[N<<1];
void add(int x,int y,int z){to[++cnt]=y,w[cnt]=z,nxt[cnt]=tp[x],tp[x]=cnt;}
bool bj[N],bjj[N],flag;
long long b[N],val;
void bfs(int x)
{
	queue<int> q;
	q.push(x),bj[x]=1,b[x]=0,k[x]=1,val=1000000000000000;
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		for(int i=tp[x];i;i=nxt[i])
			if(!bj[to[i]]) b[to[i]]=w[i]-b[x],k[to[i]]=-k[x],bj[to[i]]=1,q.push(to[i]);
			else if(!(k[to[i]]+k[x])&&b[to[i]]+b[x]!=w[i]||(k[to[i]]+k[x])&&(w[i]-b[x]-b[to[i]])%(k[x]+k[to[i]])||(k[to[i]]+k[x])&&val!=1000000000000000&&val!=(w[i]-b[x]-b[to[i]])/(k[x]+k[to[i]])) flag=1;
			else if(k[to[i]]+k[x]) val=(w[i]-b[x]-b[to[i]])/(k[x]+k[to[i]]);
	}
}
vector<pair<long long ,int> > sol;
void dfs1(int x)
{
	long long ll=k[x]==1?l[x]-b[x]:b[x]-r[x],rr=k[x]==1?r[x]-b[x]:b[x]-l[x];
	bjj[x]=1,sol.push_back({ll,1}),sol.push_back({rr+1,-1});
	for(int i=tp[x];i;i=nxt[i]) if(!bjj[to[i]]) dfs1(to[i]);
}
int dfs2(int x)
{
	bjj[x]=1;
	long long v=k[x]*val+b[x];
	int siz=(v>=l[x]&&v<=r[x]);
	for(int i=tp[x];i;i=nxt[i]) if(!bjj[to[i]]) siz+=dfs2(to[i]);
	return siz;
}
int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>t;
	while(t--)
	{
		cnt=flag=0;
		cin>>n>>m;
		for(int i=1;i<=n;i++) cin>>l[i];
		for(int i=1;i<=n;i++) cin>>r[i];
		while(m--)
		{
			int x,y,z;
			cin>>x>>y>>z;
			add(x,y,z),add(y,x,z);
		}
		int ans=0;
		for(int i=1;i<=n;i++)
			if(!bj[i])
			{
				bfs(i);
				if(val==1000000000000000)
				{
					dfs1(i),sort(sol.begin(),sol.end());
					int sum=0,max1=0;
					for(int j=0;j<sol.size();j++) sum+=sol[j].second,max1=max(max1,sum);
					ans+=max1,sol.clear();
				}
				else ans+=dfs2(i);
			}
		cout<<(flag?-1:ans)<<"\n";
		for(int i=1;i<=n;i++) tp[i]=bj[i]=bjj[i]=0;
	}
	return 0;
}
相关推荐
武子康1 小时前
驾驶轨迹换个坐标,就能给移动机器人用吗?
人工智能·算法·机器学习
David猪大卫1 小时前
【C++修炼】map 和 set 的使用
c语言·开发语言·数据结构·c++·经验分享·笔记·学习
HPtiger1 小时前
C++ 入门笔记:从 C 到 C++ 的核心过渡(命名空间、输入输出、缺省参数、重载、引用、内联)
c语言·c++·学习
vvilkim3 小时前
数据结构类型、区别与应用场景:一篇讲透选型逻辑
数据结构
努力努力再努力wz4 小时前
【Lua 进阶系列】从 C++ 对象到 Lua 变量:一文理解 userdata、Lua 栈与元表绑定机制
c++·junit·lua
慧都产品智能化5 小时前
Qt 表格升级攻略:复用已有编辑器,减少重复开发
c++·qt·编辑器·qt6.3
ShineWinsu5 小时前
对于Qt:QTableWidget常见属性以及QTableWidgetItem类的解析
开发语言·c++·qt·gui·客户端·表格·qtablewidget
ShineWinsu6 小时前
对于Qt:QListWidget常见属性以及QListWidgetItem类的解析
开发语言·c++·qt·客户端·列表·qlistwidget·qlistwidgetitem
坤坤子吖6 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
lisw057 小时前
Dayhoff的PAM替换矩阵理论评介!
线性代数·算法·矩阵