Link is developing a game. In this game, players can craft things using various types of resources, and things crafted can also be used to craft other things.
Formally speaking, there are nn types of items, numbered from 1 to n, and mm recipes in the game. In the i-th recipe, players can use k∗ai items of the bi-th type to craft k∗ci items of the di-th type, where k can be any positive real number.
One day, he finds that one player owns more than 18,446,744,073,709,551,615 identical items, which causes a server crash. This is obviously impossible without using glitches.
Link soon finds out that there is something wrong with the crafting recipe. Players may get infinite resources by crafting some special things over and over again!
Link doesn't want to adjust the recipes one by one, so he simply added an argument w. Now players can use k∗ai items of the bi-th type to craft w∗k∗ci items of the di-th type.
Link wonders: What's the maximum ww that he can set so that no player can get infinite items by crafting things over and over again?
题意:
第一行输入n,m,有n类物品,给每类物品编号1~n,有m种配方。接下来m行 包含四个整数 a b c d ,代表用a个b类物品,可以制造出c个d类物品。
然而存在无限制造的情况,比如消耗1个1类物品制造2个2类物品 ,一个2类物品有可以制造2个1类物品,现在为了杜绝这种现象,将消耗a个b制造c个d变为了消耗a个b制造c*w个d。求满足不能无限制造情况下的最大w。
思路:
如果无限制造,则必须成环,二分这个w,w一定是在0~1之间的一个数。建图,a,b,c,d建立从 b到d的边,权值为c/a,然后用spfa判环。如果存在环,且这个环是越造越少的,即不能无限制造,那么用spfa肯定是一直早跑这个环的,即遍历次数很多,用这个来判定w是否合适。如果不能无限制造代表我们的w可以更大一点,反之让w更小一点。然后精度在1e-6。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int MAXN = 1010;
const int MAXM = 3010;
const double eps=0.00000001;
int n,m,num,head[MAXN],cnt[MAXN];
double dis[MAXN];
bool vis[MAXN];
struct edge
{
int to,next;
double w;
}e[MAXM];
inline void add(int u,int v,double w)
{
e[++num].to=v;
e[num].w=w;
e[num].next=head[u];
head[u]=num;
}
inline bool spfa(double w)
{
for(int i=1;i<=n;i++)
{
dis[i]=1;
vis[i]=cnt[i]=1;
}
queue<int> q;
int u,v;
for(int i=1;i<=n;i++)
{
q.push(i);
}
while(!q.empty())
{
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].next)
{
v=e[i].to;
if(dis[v]<=dis[u]*e[i].w*w)
{
dis[v]=dis[u]*e[i].w*w;
cnt[v]=cnt[u]+1;
if(cnt[v]>n)return 1;
if(vis[v]==0)
{
vis[v]=1;
q.push(v);
}
}
}
}
return 0;
}
int main()
{
cin>>n>>m;
for(int i=1,a,b,c,d;i<=m;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
add(b,d,1.0*c/a);
}
double l=0;double r=1.0;
while(r-l>=eps)
{
double mid=(l+r)/2;
if(spfa(mid))
{
r=mid;
}
else
{
l=mid;
}
}
printf("%.7lf\n",l);
return 0;
}