[POJ3411] Paid Roads

 

题意:N个城市,经过每条边有两种代价,一种是经过了这条边给定的城市,代价为Pi,另一种是直接到对面城市,代价为Ri,求小朋友从1~N的最小代价(注:边是有向的)

 

题解:

spfa

dis[i][j]表示到i号城市经过了j状态城市的最小代价,直接搞搞傻逼转移就好了

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
using namespace std;

const int N = 11;

int n,m,e_num,ans,inf;
int nxt[N*2],to[N*2],h[N],dis[N][1<<N];
bool in[N][1<<N];

struct Edge {int c,a,b;}w[N*2];
struct Node {int x,y;};

queue<Node> q;

void add(int x, int y, int c, int a, int b) {
  nxt[++e_num]=h[x],to[e_num]=y,w[e_num]=(Edge){c,a,b},h[x]=e_num;
}

int gi() {
  int x=0,o=1; char ch=getchar();
  while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
  if(ch=='-') o=-1,ch=getchar();
  while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
  return o*x;
}

void spfa() {
  memset(dis,63,sizeof(dis));
  ans=inf=dis[0][0];
  dis[1][1]=0,in[1][1]=0,q.push((Node){1,1});
  while(!q.empty()) {
    Node u=q.front();
    int x=u.x,y=u.y;
    in[x][y]=0,q.pop();
    for(int i=h[x]; i; i=nxt[i]) {
      int v=to[i];
      if(y&(1<<(w[i].c-1))) {
	if(dis[x][y]+w[i].a<dis[v][y|(1<<(v-1))]) {
	  dis[v][y|(1<<(v-1))]=dis[x][y]+w[i].a;
	  if(!in[v][y|(1<<(v-1))]) in[v][y|(1<<(v-1))]=1,q.push((Node){v,y|(1<<(v-1))});
	}
      }
      else {
	if(dis[x][y]+w[i].b<dis[v][y|(1<<(v-1))]) {
	  dis[v][y|(1<<(v-1))]=dis[x][y]+w[i].b;
	  if(!in[v][y|(1<<(v-1))]) in[v][y|(1<<(v-1))]=1,q.push((Node){v,y|(1<<(v-1))});
	}
      }
    }
  }
}

int main() {
  while(scanf("%d%d", &n, &m)!=EOF) {
    for(int i=1; i<=m; i++) {
      int x=gi(),y=gi(),c=gi(),a=gi(),b=gi();
      add(x,y,c,a,b);//add(y,x,c,a,b);   
    }
    spfa();
    for(int i=1; i<1<<n; i++) {
      ans=min(ans,dis[n][i]);
    }
    if(ans==inf) puts("impossible");
    else printf("%d\n", ans);
  }
  return 0;
}

 

posted @ 2017-09-12 20:19  HLX_Y  阅读(145)  评论(0编辑  收藏  举报