题解 寻找道路

传送门

更遗憾的一个题,刚了两个半小时没刚出来

首先bitset按题意模拟可以有50pts,只记录最高的一千位乱搞可以有100pts
然后考场总是想着dijkstra,想设法让两个 \(2^{10^6}\) 级别的数比大小
于是炸上天了
最短路除了dij,还有一个容易忘的BFS
这里除了与点1以0边相连的点,其他的点都一定是01串更短的距离更短
所以满足BFS的性质
但难点在于处理01串长度相同的情况
考虑在BFS时先扩展0边
第一个思路是先扩所有长度相同的
发现若10,11中10能靠一个1边扩展到下一个点, 11能靠一个0边扩展到下一个点会炸
所以改成先扩所有距离相等的

  • 带有特殊性质的最短路先考虑一下这些特殊性质能不能有BFS扩展?
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define ll long long
#define fir first
#define sec second
#define make make_pair
#define pb push_back
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
int head[N], size;
const ll mod=1e9+7;
struct edge{int to, next, val;}e[N<<2];
vector<int> to0[N], to1[N];
inline void add(int s, int t, int w) {e[++size].to=t; e[size].val=w; e[size].next=head[s]; head[s]=size;}

namespace force{
	bool vis[N];
	bitset<1010> inf, tem;
	pair<bitset<1010>, ll> dis[1010];
	inline bool operator < (bitset<1010>& a, bitset<1010>& b) {
		for (int i=1009; ~i; --i) if (a[i]!=b[i]) return b[i];
		return 0;
	}
	struct ele{
		bitset<1010> s;
		int u;
		ele(){}
		ele(bitset<1010> a, int b):s(a),u(b){}
	};
	inline bool operator < (ele a, ele b) {return b.s<a.s;}
	priority_queue<ele> q;
	void solve() {
		for (int i=0; i<1010; ++i) inf[i]=1;
		for (int i=1; i<=n; ++i) dis[i].fir=inf;
		dis[1].fir.reset();
		q.push(ele(dis[1].fir, 1));
		int u;
		while (q.size()) {
			u=q.top().u; q.pop();
			if (vis[u]) continue;
			vis[u]=1;
			for (int i=head[u],v; ~i; i=e[i].next) {
				v = e[i].to;
				tem=dis[u].fir<<1;
				if (e[i].val) tem[0]=1;
				if (tem<dis[v].fir) {
					dis[v].fir=tem;
					// cout<<"val: "<<e[i].val<<endl;
					dis[v].sec=(dis[u].sec<<1|e[i].val)%mod;
					q.push(ele(dis[v].fir, v));
				}
			}
		}
		for (int i=2; i<=n; ++i)
			if (dis[i].fir==inf) printf("-1 ");
			else printf("%lld ", dis[i].sec);
		printf("\n");
		exit(0);
	}
}

namespace task{
	ll dis[N];
	vector<int> q1, q2, tem;
	queue<int> q;
	void solve() {
		memset(dis, -1, sizeof(dis));
		dis[1]=0; q.push(1);
		while (q.size()) {
			int u=q.front(); q.pop();
			q1.push_back(u);
			for (auto v:to0[u]) if (dis[v]==-1) {
				dis[v]=0;
				q.push(v);
			}
		}
		while (q1.size()) {
			// cout<<"q1: "; for (auto it:q1) cout<<bitset<10>(dis[it])<<' '; cout<<endl;
			int pos=0;
			while (pos<q1.size()) {
				tem.clear();
				tem.pb(q1[pos++]);
				while (pos<q1.size() && (dis[q1[pos-1]]==dis[q1[pos]])) tem.pb(q1[pos++]);
				for (auto u:tem) {
					for (auto v:to0[u]) if (dis[v]==-1) {
						dis[v]=(dis[u]<<1)%mod;
						q2.push_back(v);
					}
				}
				for (auto u:tem) {
					for (auto v:to1[u]) if (dis[v]==-1) {
						dis[v]=(dis[u]<<1|1)%mod;
						q2.push_back(v);
					}
				}
			}
			q1.clear();
			swap(q1, q2);
		}
		for (int i=2; i<=n; ++i) printf("%lld%c", dis[i], " \n"[i==n]);
		exit(0);
	}
}

signed main()
{
	freopen("path.in", "r", stdin);
	freopen("path.out", "w", stdout);

	n=read(); m=read();
	memset(head, -1, sizeof(head));
	for (int i=1,u,v,w; i<=m; ++i) {
		u=read(); v=read(); w=read();
		add(u, v, w);
		if (w) to1[u].pb(v);
		else to0[u].pb(v);
	}
	// force::solve();
	task::solve();

	return 0;
}
posted @ 2021-10-27 21:31  Administrator-09  阅读(0)  评论(0编辑  收藏  举报