最短路问题,然而对于任意\(i,j\),从\(i\)\(j\)可以只花费\((i xor j) \cdot C\)

对每个点\(i\),只考虑到\(j\)满足\(j=i xor 2^k, j \leq i\)

显然其它边可以由这些边组合得到

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int MAX_NODE = 500005;

template <class T> class Graph_SP { // 解决单源最短路径问题
public:
	vector<pair<int, T> >G[MAX_NODE];
	int d[MAX_NODE], v[MAX_NODE]; // 距离表与访问标识表
	void make(int t1, int t2, T t3) { // 造边(有向)
		G[t1].push_back(make_pair(t2, t3));
	}
	void reset_graph(int n) { // 用于清除图邻接表
		for (int i = 0; i <= n; i++)
			G[i].clear();
	}
	void reset_solver(int n) { // 对距离表与访问标识表的清除 如果改变了类型,该函数可能需要重写!
		memset(d, 0x3f, sizeof d);
		memset(v, 0x00, sizeof v);
	}
	void solveDijkstra(int v0, int n) { // 执行主计算任务(使用Dijkstra)
		priority_queue<pair<T, int>, vector<pair<T, int> >, greater<pair<T, int> > >q;
		reset_solver(n); // 自动调用对距离表与访问标识表的清除
		d[v0] = 0;
		q.push(make_pair(0, v0));
		while (q.size()) {
			pair<T, int> p = q.top();
			T dis = p.first; // dis为到当前点的距离
			int pos = p.second; // pos为当前点
			q.pop();
			v[pos] = 1;
			for (int i = 0; i < G[pos].size(); i++) {
				int x = G[pos][i].first; // x为当前枚举边的终点,
				T y = G[pos][i].second; // y为当前枚举边的权值
				if (d[x] > d[pos] + y) {
					d[x] = d[pos] + y;
					if (!v[x])
						q.push(make_pair(d[x], x));
				}
			}
		}
	}
} ;
Graph_SP <int> g;

signed main() {
    int n,m,k,t1,t2,t3,a,b;
    scanf("%lld%lld%lld",&n,&m,&k);
    for(int i=1;i<=m;i++) {
        scanf("%lld%lld%lld",&t1,&t2,&t3);
        g.make(t1,t2,t3);
    }
    scanf("%lld%lld",&a,&b);
    for(int i=0;i<=n;i++) {
        for(int p=0;p<=20;p++) {
            int j=i^(1ll<<p);
            if(j<=n) g.make(i,j,k*(1ll<<p));
        }
    }
    g.solveDijkstra(a,n);
    cout<<g.d[b]<<endl;
}

相关文章: