分块 wa 18 求调
查看原帖
分块 wa 18 求调
353688
王熙文楼主2023/10/13 23:29

不想写主席树所以写了分块。思路和主席树类似,考虑将每个数的二进制分块,每一次加法最多新增两个块,暴力维护。

对拍拍不出来,且换过哈希方式仍然 wa,感觉可能是逻辑上写挂了,但是看不出来。

代码:

#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
int n,m,s,t;
vector<pair<int,int>> e[100010];
int block=350;
int tot=2; int dis[200010][360]; int hsh[200010];
vector<int> wz[100010];
bool cmp(vector<int> wz1,vector<int> wz2)
{
	for(int i=block-1; i>=0; --i)
	{
		if(hsh[wz1[i]]!=hsh[wz2[i]])
		{
			for(int j=block; j>=1; --j)
			{
				if(dis[wz1[i]][j]!=dis[wz2[i]][j]) return dis[wz1[i]][j]<dis[wz2[i]][j];
			}
		}
	}
	return 1;
}
vector<int> add(int x,int w)
{
	vector<int> now;
	for(int i=0; i<=block-1; ++i)
	{
		if((i+1)*block-1<w) now.push_back(wz[x][i]);
		else
		{
			bool flag=1;
			int ed;
			for(int j=w-i*block+1; j<=block; ++j)
			{
				if(dis[wz[x][i]][j]==0) { flag=0,ed=j; break; }
			}
			if(flag)
			{
				++tot;
				memcpy(dis[tot],dis[wz[x][i]],sizeof(dis[wz[x][i]]));
				for(int j=w-i*block+1; j<=block; ++j) dis[tot][j]=0;
				for(int j=1; j<=block; ++j) hsh[tot]=(hsh[tot]*2+dis[tot][j])%mod;
				now.push_back(tot);
				int wwz=i+1;
				while(hsh[wwz]==hsh[2]) now.push_back(1),++wwz;
				for(int j=1; j<=block; ++j)
				{
					if(dis[wz[x][wwz]][j]==0) { ed=j; break; }
				}
				++tot;
				memcpy(dis[tot],dis[wz[x][wwz]],sizeof(dis[wz[x][wwz]]));
				for(int j=1; j<ed; ++j) dis[tot][j]=0;
				dis[tot][ed]=1;
				for(int j=1; j<=block; ++j) hsh[tot]=(hsh[tot]*2+dis[tot][j])%mod;
				now.push_back(tot);
				for(int j=wwz+1; j<=block-1; ++j) now.push_back(wz[x][j]);
			}
			else
			{
				++tot;
				memcpy(dis[tot],dis[wz[x][i]],sizeof(dis[wz[x][i]]));
				for(int j=w-i*block+1; j<ed; ++j) dis[tot][j]=0;
				dis[tot][ed]=1;
				for(int j=1; j<=block; ++j) hsh[tot]=(hsh[tot]*2+dis[tot][j])%mod;
				now.push_back(tot);
				for(int j=i+1; j<=block-1; ++j) now.push_back(wz[x][j]);
			}
			return now;
		}
	}
}
struct Prio
{
	int now; vector<int> wz;
	bool operator < (Prio x) const
	{
		return cmp(x.wz,wz);
	}
}; priority_queue<Prio> q;
bool vis[100010];
int pre[100010];
int main()
{
	cin>>n>>m;
	for(int i=1; i<=m; ++i)
	{
		int u,v,w; cin>>u>>v>>w;
		e[u].push_back({v,w}),e[v].push_back({u,w});
	}
	cin>>s>>t;
	for(int i=1; i<=block; ++i) hsh[2]=(hsh[2]*2+1)%mod;
	for(int i=1; i<=block; ++i) dis[2][i]=1;
	for(int i=1; i<=n; ++i)
	{
		for(int j=1; j<=block; ++j) wz[i].push_back(i==s?1:2);
	}
	q.push({s,wz[s]});
	while(!q.empty())
	{
		int frn=q.top().now; q.pop();
		if(vis[frn]) continue; vis[frn]=1;
		for(pair<int,int> vv:e[frn])
		{
			int v=vv.first,w=vv.second;
			if(vis[v]) continue;
			vector<int> gt=add(frn,w);
			if(cmp(gt,wz[v])) wz[v]=gt,q.push({v,wz[v]}),pre[v]=frn;
		}
	}
	if(!vis[t]) return cout<<-1,0;
	int ans=0,pow2=1;
	for(int i=0; i<=block-1; ++i)
	{
		for(int j=1; j<=block; ++j) ans=(ans+dis[wz[t][i]][j]*pow2)%mod,pow2=pow2*2%mod;
	}
	cout<<ans<<'\n';
	stack<int> st;
	while(t!=s) st.push(t),t=pre[t];
	st.push(s);
	cout<<st.size()<<'\n';
	while(!st.empty()) cout<<st.top()<<' ',st.pop();
	return 0;
}
2023/10/13 23:29
加载中...