hdu 2020多校 round4 Deliver the Cake

题意

给一个无向图,n个点,m条边条边。
每个点有一个属性:LRM。
到哪个点需要和他属性保持一致,M是任意属性。
L与R相互转换需要消耗时间x。求最短路。
比传统的最短路来说,多了些变化。我们可以把需要L与R转换的边权值加个x.
由于存在M的点可以是L或R,我们将其拆分成两个点值分别是L和R就行。
注意当起点或是终点是M时,会有两个起点或终点。我们在外面建一个源点就行了。

代码:

#include
#define ll long long
#define p pair
using namespace std;
const int N=2e6+10;
int h[N],to[N],ne[N],cnt,vis[N];
ll cost[N],w,dis[N];
int n,m,s,t,x;
int u,v;
char str[N];
inline ll rd()
{
    register ll s=0,w=1;
    register char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        s=s*10+ch-'0';
        ch=getchar();
    }
    return s*w;
}
void add(int u,int v,int w){
    cost[cnt]=w,to[cnt]=v,ne[cnt]=h[u],h[u]=cnt++;
}
ll dij(){
    memset(dis,1e9+7,sizeof(dis));
    if(str[s]=='M') dis[0]=0;
    else dis[s]=0;
    priority_queue,greater

>q; if(str[s]=='M') q.push({0,0}); else q.push({0,s}); while(!q.empty()){ p id=q.top(); q.pop(); int u=id.second; vis[u]=1; for(int i=h[u];~i;i=ne[i]){ int k=to[i]; //printf("u=%d,k=%d,r=%d,hand=%c\n",u,k,r,hand); if(dis[k]>dis[u]+cost[i]) { dis[k]=dis[u]+cost[i]; q.push({dis[k],k}); } } } if(str[t]= ='M')return dis[2*n+1]; else return dis[t]; } int main(){ int o; o=rd(); while(o--){ memset(h,-1,sizeof(h)); memset(vis,0,sizeof(vis)); cnt=0; n=rd(),m=rd(),s=rd(),t=rd(),x=rd(); for(int i=1;i<=n;i++) scanf("%c",&str[i]); if(str[s]= ='M') { add(0,s,0), add(s,0,0); add(0,s+n,0), add(s+n,0,0); } if(str[t]= ='M') { add(2*n+1,t,0), add(t,2*n+1,0); add(2*n+1,t+n,0), add(t+n,2*n+1,0); } for(int i=1;i<=m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); if((str[a]= ='L'&&str[b]= ='R') || (str[a]= ='R'&&str[b]= ='L')) { add(a,b,c+x), add(b,a,c+x); //LR or RL } else if((str[a]=='L'&&str[b]=='L') || (str[a]=='R'&&str[b]=='R')) { add(a,b,c), add(b,a,c); //LL or RR } else if(str[a]=='L'&&str[b]=='M') { add(a,b,c), add(b,a,c); // LL add(a,n+b,c+x), add(n+b,a,c+x); //LR } else if(str[a]=='M'&&str[b]=='L') { add(a,b,c), add(b,a,c); //LL add(a+n,b,c+x), add(b,a+n,c+x); //RL } else if(str[a]=='R'&&str[b]=='M') { add(a,b,c+x), add(b,a,c+x); //RL add(a,n+b,c), add(n+b,a,c); //RR } else if(str[a]=='M'&&str[b]=='R') { add(a,b,c+x), add(b,a,c+x); //LR add(a+n,b,c), add(b,a+n,c); //RR } else if(str[a]=='M'&&str[b]=='M') { add(a,b,c), add(b,a,c); //LL add(a,b+n,c+x), add(b+n,a,c+x); //LR add(a+n,b,c+x), add(b,a+n,c+x); //RL add(a+n,b+n,c), add(b+n,a+n,c); //RR } } printf("%lld\n",dij()); } return 0; }

你可能感兴趣的:(题解,#图论,c++,图论,算法)