POJ 1062 - 昂贵的聘礼 - 经典题

1.Question:

中文题不说什么了

2.Solution:

本题的难点有两个
1.建图
2.限制

建图:
首先,我们需要明确本图G是一个有向图,我们的顶点代表庙我们的物品的编号,图采用邻接矩阵存储,我们的图中的邻接矩阵中存储我们的便宜价格这样的话,我们每个点只要在限制条件下都可以找到1点,那么我们就取到达1点的最小值当作我们的答案

限制:
本体的限制说的很明确,但是我们如何处理我们的限制确实非常的苦难,网上的大神采用了区间枚举的思路,我们对SPFA进行操作的时候,我们的松弛百年志松驰在限制区间范围的边才可以

另外,通过本体需要学会一种叫做超级源点的思路,我们的0视作超级源点,该点和其他的点之间的都有连边,连边的长度大小是我们的该点除的物品的权值,超级源点的思路非常的有用

3.Code:

/*
Problem: 1062		User: lantianheyeqi
Memory: 240K		Time: 32MS
Language: C++		Result: Accepted
*/
#include"iostream"
#include"cstdio"
#include"cstring"
#include"cstdlib"
#include"cmath"
#define N 0x3f3f3f3f

int n,m;
int map[105][105];
int l[105];

void init_map()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i!=j) map[i][j]=N;
			else map[i][j]=0;
		}
	}
}

int SPFA(int j,int k)
{
	int queue[100*100];
	int head=1;
	int tail=2;
	bool book[105];
	memset(book,0,sizeof(book));
	book[0]=1;
	queue[1]=0;
	int dis[105];
	for(int i=1;i<=n;i++) dis[i]=N;
	dis[0]=0;
	while(head!=tail)
	{
		for(int i=1;i<=n;i++)
		{
			if(l[i] < j || l[i] > k) continue;
			if(dis[i] > dis[queue[head]]+map[queue[head]][i])
			{
				dis[i] = dis[queue[head]]+map[queue[head]][i];
				if(book[i]==0)
				{
					book[i]=1;
					queue[tail++]=i;
				}
			}
		}
		book[queue[head]]=0;
		head++;
	}
	return dis[1];
}

int main()
{
	scanf("%d%d",&m,&n);
	init_map();
	for(int i=1;i<=n;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		map[0][i]=x;
		l[i]=y;
		for(int j=1;j<=z;j++)
		{
			int number,money;
			scanf("%d%d",&number,&money);
			map[number][i]=money;
		}
	}
	int mink=N;
	for(int i=l[1]-m;i<=l[1];i++)
	{
		int w=SPFA(i,i+m);
		if(w


你可能感兴趣的:(ACMer's,collection,图,POJ,专项题解)