开心小屋(smile)【DFS】【环】

   日期:2020-08-20     浏览:83    评论:0    
核心提示:>DescriptionKc来到开心小屋。开心小屋是用来提升心情的。在这个小屋中有n个房间,一些房间之间有门连通。从房间i到达房间j,心情值可以加上-10000<=Cij<=10000,当然Cij可能是负的。现在kc失恋了,所以他想要知道他是否可以在这个小屋中无限地增加他的心情值,也就是无限地绕着一个环走?请帮kc求出最小的环需要经过的房间数,来使他的心情无限增加。>Input第一行给出,1<=n<=300,1<=m<=5000。分别表示房间数及门的

>Description
Kc来到开心小屋。开心小屋是用来提升心情的。在这个小屋中有n个房间,一些房间之间有门连通。从房间i到达房间j,心情值可以加上-10000<=Cij<=10000,当然Cij可能是负的。现在kc失恋了,所以他想要知道他是否可以在这个小屋中无限地增加他的心情值,也就是无限地绕着一个环走?

请帮kc求出最小的环需要经过的房间数,来使他的心情无限增加。

>Input
第一行给出,1<=n<=300,1<=m<=5000。分别表示房间数及门的数量。
接下来m行,每行四个数:i,j,Cij,Cji

>Output
输出文件包括一行,及最小的环需要经过的房间数。
保证不会出现自环及重边。

对30%的数据,n<=10;
对60%的数据,,n<=100;
对100%的数据,n<=300;

>解题思路
竟然真的直接爆搜就过了TT

把每个点都当做start跑一遍dfs,如果再跑回start并且是个正环就累计答案,
因为跑dfs都会做标记防止在跑回去,但是我们判断环的话为了跑回原来的start,就不标记start这个点

还有一些剪枝:
当前代价为负数就return,因为我们要求的是一个正环,所以对于环中的每一个点都可以作为start,那么一定有一个点作为start的sum不会为负数(“用心理解”)
如果当前的路径数大于ans的话就return

>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#define N 305
using namespace std;

struct line
{
	int to, next, c;
} a[10005];
int n, m, t, h[N], ans, start;
bool s[N], y[N];

void add (int x, int y, int l)
{
	a[++t] = (line) {y, h[x], l}; h[x] = t;
}
void dfs (int now, int c, int cnt)
{
	if (c < 0 || cnt > ans) return;
	if (now == start && cnt > 0)
	{
		if (c > 0) ans = min (ans, cnt);
		return;
	}
	for (int i = h[now]; i; i = a[i].next)
	  if (!y[a[i].to])
	  {
	  	y[a[i].to] = 1; //标记
		dfs (a[i].to, c + a[i].c, cnt + 1);
		y[a[i].to] = 0;
	  }
}

int main()
{
	ans = 300;
	scanf ("%d%d", &n, &m);
	int u, v, l;
	for (int i = 1; i <= m; i++)
	{
		scanf ("%d%d", &u, &v);
		scanf ("%d", &l);
		add (u, v, l);
		scanf ("%d", &l);
		add (v, u, l);
	}
	for (int i = 1; i <= n; i++)
	{
	  	start = i;
	  	dfs (i, 0, 0);
	}
	printf ("%d", ans);
	return 0;
}
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服