首页 > 代码库 > POJ 3411-Paid Roads(DFS)

POJ 3411-Paid Roads(DFS)

题目链接:传送门

题意:n个城市,m条道路,要求1--N的最小花费。规定从a城市到城市的花费有两种:如果之前到过c,花费为p,否则花费为r。注意:道路是双向的。

难点:可能a到b有多条路而且花费不同这样的话邻接矩阵会错;有人可能深搜的时候会让每个城市只走一次(DFS惯性思维),但这道题不一样,因为到达下一个城市之前可能需要先到另外一个城市以降低花费。这样的话可以标记每个城市访问过的次数,可以设定让它不超过10次,网上说是3次其实这都无所谓,因为可以加一个最优化剪枝那样就算设为20次也能过(设为20的时候我跑过219ms,10次是0ms)最优化剪枝就是如果当前答案大于已经搜到最优答案,剪掉。

注意有可能无解。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cctype>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define maxn 360
#define _ll __int64
#define ll long long
#define INF 0x3f3f3f3f
#define Mod 1000000007
#define pp pair<int,int>
#define ull unsigned long long
#define max(x,y) ( ((x) > (y)) ? (x) : (y) )
#define min(x,y) ( ((x) > (y)) ? (y) : (x) )
using namespace std;
struct node
{
	int u,c,wa,wb;
	node (int a,int b,int x,int y)
	{
		u=a;c=b;wa=x;wb=y;
	}
};
vector <node> eg[12];
int ok,ma[12][12][2],n,m,vis[12],ans;
void init()
{
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++)
		eg[i].clear();
}
void dfs(int u,int s)
{
	if(s>ans)return ;
	if(u==n)
	{
		ok=1;ans=min(ans,s);
		return ;
	}
	for(int i=0;i<eg[u].size();i++)
	{
		int v=eg[u][i].u;
		if(vis[v]<=20)
		{
			vis[v]++;
			if(vis[eg[u][i].c])
			dfs(v,s+eg[u][i].wa);
			else
			dfs(v,s+eg[u][i].wb);
			vis[v]--;
		}
	}
}
int main()
{
	int u,v,c,wa,wb;
	while(~scanf("%d%d",&n,&m))
	{
		init();
		while(m--)
		{
			scanf("%d%d%d%d%d",&u,&v,&c,&wa,&wb);
			eg[u].push_back(node(v,c,wa,wb));
		}
		ans=INF;ok=0;dfs(1,0);
		if(ok)
			printf("%d\n",ans);
		else
			puts("impossible");
	}
	return 0;
}



POJ 3411-Paid Roads(DFS)