http://poj.org/problem?id=3411
大致题意:n个城市由m条公路连接,两个城市之间可能有多条公路连接。经过每条公路都需要收费,对于城市a,b,若之前经过城市c那么只需交p元钱,否则交r元钱。问从城市1到n的最小花费。
思路:由于经过每条公路的收费有两种方式,那么有的城市可能要经过多次,以便获得更小的花费,但也有可能出现有环的情况,那么该城市经过多次只会徒增花费。所以我们定义vis[]数组标记该城市访问的次数,在该题中(m <= 10)当一个城市访问超过3次(网上说这个与图的边数m有关)就可判定它在环中,没必要继续搜了。
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#define LL long long
#define _LL __int64
#define eps 1e-8
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 110;
struct node
{
int v,c,p,r;
};
vector <node> edge[20];
int n,m;
int vis[20];
int ans;
void dfs(int u, int cost)
{
if(cost >= ans)
return;
if(u == n)
{
if(ans > cost)
ans = cost;
return;
}
for(int i = 0; i < (int)edge[u].size(); i++)
{
int v = edge[u][i].v;
if ( vis[v] <= 3 ) //搜索的限制条件,避免一个点走过超过3次出现环路。之前没加RE了。
{
vis[v]++;
if ( vis[edge[u][i].c])
dfs(v, cost + edge[u][i].p);
else
dfs(v, cost + edge[u][i].r);
vis[v]--;
}
}
}
int main()
{
int a,b,c,p,r;
while(~scanf("%d %d",&n,&m))
{
for(int i = 0; i <= n; i++)
edge[i].clear();
for(int i = 0; i < m; i++)
{
scanf("%d %d %d %d %d",&a,&b,&c,&p,&r);
edge[a].push_back((struct node){b,c,p,r});
}
memset(vis,0,sizeof(vis));
ans = INF;
vis[1] = 1;
dfs(1,0);
if(ans == INF)
printf("impossible\n");
else printf("%d\n",ans);
}
return 0;
}