题目大意:
给一个
n
个点
分析:
二分最大值
k
,我们只需要求
AC code:
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#define pb push_back
#define ONLINE_JUDGE
typedef double DB;
using namespace std;
const int MAXN = 59;
const int MAXM = 2509;
const int MAXT = 5009;
const DB eps = 1e-10;
const DB INF = 1e10;
int n, m;
int f[MAXT];
struct Dgraph
{
int size;
int head[MAXN];
int to[MAXM];
DB c[MAXM], t[MAXM];
int ne[MAXM];
Dgraph(){size = 1;}
void add_edge(int u, int v, DB C, DB T)
{
to[size] = v, c[size] = C, t[size] = T, ne[size] = head[u], head[u] = size++;
}
}G;
bool vis[MAXN];
DB dis[MAXN];
int fr[MAXN];
int inq[MAXN];
vector<int> ans;
int spfa(DB k)
{
queue<int> q;
for(int i = 1; i <= n; ++i) dis[i] = INF;
memset(fr, 0, sizeof(fr));
memset(inq, 0, sizeof(inq));
memset(vis, false, sizeof(vis));
q.push(1), inq[1] = 1, vis[1] = true, dis[1] = 0;
while(!q.empty())
{
DB d;
int u = q.front(), v;
q.pop();
vis[u] = false;
if(inq[u] > n) return u;
for(int i = G.head[u]; i; i = G.ne[i])
{
v = G.to[i];
d = k*G.t[i]-G.c[i];
if(dis[v] > dis[u]+d)
{
fr[v] = u;
dis[v] = dis[u]+d;
if(!vis[v])
{
inq[v]++;
vis[v] = true;
q.push(v);
}
}
}
}
return 0;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu236.in", "r", stdin);
freopen("sgu236.out", "w", stdout);
#endif
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++i)
{
int u, v;DB C, T;
scanf("%d%d%lf%lf", &u, &v, &C, &T);
G.add_edge(u, v, C, T);
}
DB l = eps, r = INF;
while(l+eps <= r)
{
DB mid = (l+r)*0.5;
if(spfa(mid)) l = mid;
else r = mid;
}
int st = spfa(l);
if(!st) {puts("0");return 0;}
memset(inq, 0, sizeof(inq));
for(int i = st; inq[i] <= 1; i = fr[i])
if(++inq[i] == 2) ans.pb(i);
printf("%d\n", ans.size());
for(int i = ans.size()-1; i >= 0; --i)
printf("%d%c", ans[i], i==0?'\n':' ');
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}