HDU 6805 Deliver the Cake(拆点重构+最短路)
题意:给出一个无向图,每个点有三种状态LRM,每个点到下一个点的时候L->R和R->L都需要额外付出x的代价,M表示都接受且不用付出额外代价。求S到T的最少代价。
题解:把状态为M的点拆成状态L的点,和状态R的两个点重新建图,跑dijkstra时候转移的时候看看是否需要付出额外的代价即可,为了方便每个点都拆分成2个点。
#include <bits/stdc++.h> #define IO_read ios::sync_with_stdio(false);cin.tie(0) #define fre freopen("in.txt", "r", stdin) #define _for(i,a,b) for(int i=a; i< b; i++) #define _rep(i,a,b) for(int i=a; i<=b; i++) #define inf 0x3f3f3f3f #define lowbit(a) ((a)&-(a)) using namespace std; typedef long long ll; template <class T> void read(T &x) { char c; bool op=0; while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1; x=c-'0'; while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0'; if(op) x=-x; } template <class T> void write(T x) { if(x<0) putchar('-'), x=-x; if(x>=10) write(x/10); putchar('0'+x%10); } const int maxn=2e5+5; const long long inf_ll= (ll)1<<61; struct qnode{ int v; ll c; qnode(int _v=0, ll _c=0):v(_v), c(_c) {} bool operator <(const qnode &r) const{ return c>r.c; } }; struct Edge{ int v; ll cost; Edge(int _v=0, ll _cost=0): v(_v), cost(_cost){} }; vector<Edge> E[maxn*4]; bool vis[maxn]; ll dis[maxn]; int pre[maxn]; int T, n, m, s, t, x; char str[maxn]; int lim[maxn]; void dijkstra(int n, int start) { memset(vis, 0, sizeof(vis)); for(int i=1; i<=n; i++) dis[i]=inf_ll; priority_queue<qnode> que; que.push(qnode(start, 0)); dis[start]=0; while(!que.empty()) { qnode tmp=que.top(); que.pop(); int u=tmp.v; if(vis[u]) continue; vis[u]=true; for(int i=0; i<E[u].size(); i++) { int v=E[u][i].v; ll cost=E[u][i].cost; int ok=lim[u]==lim[v]? 0:1; if(!vis[v] && dis[v]>dis[u]+cost+ok*x) { dis[v]=dis[u]+cost+ok*x; pre[v]=u; que.push(qnode(v, dis[v])); } } } } void addedge(int u, int v, int w) { E[u].push_back(Edge(v, w)); E[v].push_back(Edge(u, w)); } void build(int u, int v, int w) { addedge(u, v, w); addedge(u+n, v, w); addedge(u, v+n, w); addedge(u+n, v+n, w); } int main() { read(T); while(T--) { read(n), read(m), read(s), read(t), read(x); _rep(i, 1, 2*n) E[i].clear(); scanf("%s", str+1); _rep(i, 1, n){ if(str[i]=='L') lim[i]=lim[i+n]=0; else if(str[i]=='R') lim[i]=lim[i+n]=1; else lim[i]=0, lim[i+n]=1; } _rep(i, 1, m){ int u, v, w; read(u), read(v), read(w); build(u, v, w); } long long ans=inf; if(str[s]=='L' || str[s]=='R'){ dijkstra(2*n, s); ans=min(dis[t], dis[t+n]); } else{ dijkstra(2*n, s); ans=min(dis[t], dis[t+n]); dijkstra(2*n, s+n); ans=min(ans, min(dis[t], dis[t+n])); } printf("%lld\n", ans); } return 0; }