这里所用的分数规划的公式是len1+len2+len3 = ans * 3
即 0 = ans - len1 + ans - len2 + ans - len3
用负环来判断这个公式中ans是否能够继续变大
原因是如果用ans - len 作为每一个边的权重,那么负环就是相当于得到 0 > ans - len1 + ans - len2 + ans - len3 即ans可以变大,所以就这样达到目的。
注意的是不能够把len - ans作为边的权重,即不能够把边权取相反数,因为上面判负环的情形是只要有负环存在,那么就能够获得更大的ans。 但是如果去了反之后, 就是只要有负环存在,ans就能够继续变小,通过这个判定无法得知当前ans是否能够变大,反而只是知道了ans是否能够变小,如果硬要用边权取反的形式来判断应该是需要保证有至少一个正环的情况下可以让ans继续变大。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define min(i, j) (i < j ? i : j)
#define max(i, j) (i > j ? i : j)
const int maxn = 5e5 + 60;
const int maxm = 5e5 + 60;
vector<int> G[maxn];
vector<int> l[maxn];
map<string, int> ma;
int orival[maxn];
char saveori[maxn];
char temp[maxn];
double dis[maxn];
int inqcnt[maxn];
int inq[maxn];
int idcnt = 0;
int vis[maxn];
int dfs(int s, double ans)
{
vis[s] = 1;
for (int i = 0; i < G[s].size(); i++)
{
int d = G[s][i];
int len = l[s][i];
//double reallen = (len * 1.0 / ans - 1);
double reallen = len - ans;
if (dis[d] > dis[s] + reallen)
{
dis[d] = dis[s] + reallen;
if (vis[d] || dfs(d, ans))
return 1;
}
}
vis[s] = 0;
return 0;
}
bool func(int s, double ans)
{
for (int i = 1; i <= idcnt; i++)
{
dis[i] = 33333333333.3;
vis[i] = 0;
}
for (int i = 1; i <= idcnt; i++)
{
if (dfs(i, ans)){
// return 1;
}
else
{
return 1;
}
}
return 0;
}
void solve()
{
int n;
cin >> n;
int val = 0;
for (int i = 1; i <= n; i++)
{
val = 0;
scanf("%s", saveori + 1);
int len = strlen(saveori + 1);
int arr = 1;
string s = "", t = "";
while (arr <= len)
{
int temparr = 0;
if (saveori[arr] == ' ')
{
arr++;
continue;
}
while (saveori[arr] != '-' && saveori[arr] != '\n' && arr <= len)
{
temp[temparr++] = saveori[arr++];
}
arr++;
if (temparr)
{
if (temp[0] == 'S')
{
val += 1000;
}
else if (temp[0] == 'G')
{
val += 500;
}
else if (temp[0] == 'D')
{
val += 300;
}
else if (temp[0] == 'T')
{
val += 200;
}
else if (temp[0] == 'K')
{
val += 150;
}
}
temp[temparr] = '\0';
if (s.size() == 0)
{
s = string(temp);
}
t = string(temp);
}
if (!ma.count(t))
{
ma[t] = ++idcnt;
}
if (!ma.count(s))
{
ma[s] = ++idcnt;
}
G[ma[s]].push_back(ma[t]);
l[ma[s]].push_back(val);
}
double r = 0x7fffffff;
double l = 0.00000001;
double ans = -1.0;
while (r - l >= 0.0001)
{
double mid = (r + l) / 2.0;
int res = func(1, mid);
if (res == 0)
{
ans = mid;
l = mid;
}
else
{
r = mid;
}
}
// ans = (l + r) / 2;
printf("%.0f\n", ans);
}
int main()
{
// cout << (1500.0 / 1285 - 1.0) + (1500.0 / 1285 - 1.0) + (850.0 / 1285 - 1.0) << endl;
freopen("in.txt", "r", stdin);
int T;
solve();
}