首页 > 代码库 > poj 3411 Paid Roads(dfs,可重复访问节点)

poj 3411 Paid Roads(dfs,可重复访问节点)

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;
}