分数规划,搜索参数P,把边权调整成val-p,然后找负环,如果存在负环说明答案可行并且还存在更优解,搜到精度满足即可。

minhoop
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #define maxn 10000
 7 #define maxm 50000
 8 using namespace std;
 9 struct et
10 {
11         int s,t,next;
12         double val,cost;
13 }e[maxm];
14 int v[maxn],fir[maxn];
15 double dis[maxn];
16 int n,m,tot;
17 
18 bool find(int now)
19 {
20         v[now]=1;
21         for (int j=fir[now];j;j=e[j].next)
22         {
23                 int k=e[j].t;
24                 if (dis[now]+e[j].cost<dis[k])
25                 {
26                         if (!v[k])
27                         {
28                                 dis[k]=dis[now]+e[j].cost;
29                                 if (find(k))
30                                         {
31                                                 v[now]=0;
32                                                 return 1;
33                                         }
34                         }
35                         else
36                         {
37                                 v[now]=0;
38                                 return 1;
39                         }
40                 }
41         }
42         v[now]=0;
43         return 0;
44 }
45 
46 bool judge(double p)
47 {
48         for (int i=1;i<=tot;i++) e[i].cost=e[i].val-p;
49         for (int i=1;i<=n;i++) dis[i]=0;
50         for (int i=1;i<=n;i++) if (find(i)) return 1;
51         return 0;
52 }
53 
54 void add(int x,int y,double z)
55 {
56         e[++tot].s=x; e[tot].t=y; e[tot].val=z; 
57         e[tot].next=fir[x]; fir[x]=tot;
58 }
59 
60 int main()
61 {
62         freopen("1486.in","r",stdin);
63         scanf("%d %d",&n,&m);
64         int x,y;
65         double z;
66         for (int i=1;i<=m;i++)
67         {
68                 scanf("%d %d %lf",&x,&y,&z);
69                 add(x,y,z);
70         }
71         double l=-1e7,r=1e7,ans=0;
72         while (l-r<=1e-9)
73         {
74                 double mid=(l+r)/2;
75                         //cout<<mid<<endl;
76                 if (judge(mid)) r=mid-(1e-9),ans=mid;
77                 else l=mid+(1e-9);
78         }
79         printf("%.8lf",ans);
80         return 0;
81 }

 

相关文章: