D e s c r i p t i o n Description Description
Kc来到开心小屋。开心小屋是用来提升心情的。在这个小屋中有n个房间,一些房间之间有门连通。从房间i到达房间j,心情值可以加上-10000<=Cij<=10000,当然Cij可能是负的。现在kc失恋了,所以他想要知道他是否可以在这个小屋中无限地增加他的心情值,也就是无限地绕着一个环走?
请帮kc求出最小的环需要经过的房间数,来使他的心情无限增加。
I n p u t Input Input
第一行给出,1<=n<=300,1<=m<=5000。分别表示房间数及门的数量。
接下来m行,每行四个数:i,j,Cij,Cji
O u t p u t Output Output
输出文件包括一行,及最小的环需要经过的房间数。
保证不会出现自环及重边。
S a m p l e Sample Sample I n p u t Input Input
4 4
1 2 -10 3
1 3 1 -10
2 4 -10 -1
3 4 0 -3
S a m p l e Sample Sample O u t p u t Output Output
4
H i n t Hint Hint
1—>3—>4–>2–>1为最小的符合题意的环长度为4.
对30%的数据,n<=10;
对60%的数据,,n<=100;
对100%的数据,n<=300;
T r a i n Train Train o f of of T h o u g h t Thought Thought
暴力+剪枝
要找到环,就需要从 k k k点出发再走回 k k k点
所以我们可以从 k k k点出发的时候,不把 k k k点标记
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int A[305][305], B[305];
int Ans, n, m, x, y;
void Dfs(int now, int Sum, int l, int k)
{
if(Sum > Ans || l < 0)return;//当心情小于0可以直接退出
if(now == k && Sum > 0)
{
if(l > 0)Ans = min(Ans, Sum);
return;
}
for(int i = 1; i <= n; ++i)
if(!B[i] && A[now][i] < 10000)
{
B[i] = 1;
Dfs(i, Sum + 1, l + A[now][i], k);
B[i] = 0;
}
return;
}
int main()
{
scanf("%d%d", &n, &m);
memset(A, 0x3f, sizeof(A));
for(int i = 1; i <= m; ++i)
{
scanf("%d%d", &x, &y);
scanf("%d%d", &A[x][y], &A[y][x]);
}
Ans = 1e9;
for(int i = 1; i <= n; ++i)
Dfs(i, 0, 0, i);
printf("%d", Ans);
return 0;
}