B. Minimum Average Path ###K //K

题目链接:https://codeforces.ml/edu/course/2/lesson/6/4/practice/status

题意:给定一张有向图 问1到n 权值的平均值 最小的 路径是哪条

思路: 二分check 平均值 把每条边 减去平均值得到贡献

最终1~n 距离小于0的 即为合法 因为有负边权的最短路  所以掏出spfa冲过去

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define ull unsigned long long
  5 #define pb push_back
  6 #define pi pair<int,double>
  7 #define fi first
  8 #define sc second
  9 
 10 const int maxn=1e5+10;
 11 const int mod=1e9+7;
 12 
 13 vector<pi>E[maxn];
 14 double d[maxn];
 15 int st[maxn];
 16 int n,m;
 17 
 18 struct ac
 19 {
 20     int u,v,w;
 21 };
 22 ac a[maxn];
 23 vector<int>ans;
 24 int pre[maxn];
 25 
 26 bool check(double x)
 27 {
 28     for(int i=1;i<=n;i++)
 29     {
 30         st[i]=0;
 31         E[i].clear();
 32         d[i]=1e9;
 33     }
 34     for(int i=1;i<=m;i++)
 35     {
 36         int u=a[i].u,v=a[i].v,w=a[i].w;
 37         double y=w-x;
 38         E[u].pb({v,y});
 39     }
 40 
 41     queue<int>q;
 42     st[1]=1;
 43     q.push(1);
 44     d[1]=0;
 45 
 46     while(!q.empty())
 47     {
 48         int u=q.front();
 49         q.pop();
 50         st[u]=0;
 51 
 52         for(auto &v:E[u])
 53         {
 54             if(d[v.fi]>d[u]+v.sc)
 55             {
 56                 pre[v.fi]=u;
 57                 d[v.fi]=d[u]+v.sc;
 58                 if(st[v.fi]) continue;
 59                 q.push(v.fi);
 60                 st[v.fi]=1;
 61             }
 62         }
 63     }
 64 
 65     if(d[n]<=0)
 66     {
 67         int k=n;
 68         vector<int>cnt;
 69         pre[0]=-1;
 70         while(pre[k]!=-1)
 71         {
 72             cnt.pb(k);
 73             k=pre[k];
 74         }
 75         ans=cnt;
 76         return 1;
 77     }
 78     return 0;
 79 }
 80 
 81 
 82 
 83 int main()
 84 {
 85     ios::sync_with_stdio(0);
 86     cin.tie(0);
 87     cin>>n>>m;
 88     for(int i=1;i<=m;i++)
 89     {
 90         int u,v,w;
 91         cin>>u>>v>>w;
 92         a[i]={u,v,w};
 93     }
 94     double l=0,r=100;
 95     for(int i=0;i<100;i++)
 96     {
 97         double mid=(l+r)/2;
 98         if(check(mid)) r=mid;
 99         else l=mid;
100     }
101     reverse(ans.begin(),ans.end());
102     int len=ans.size();
103     cout<<len-1<<'\n';
104     for(int i=0;i<len;i++)
105     {
106         if(i!=0) cout<<" ";
107         cout<<ans[i];
108     }
109 
110 
111 
112 
113 
114 
115 
116 
117 }
View Code

 

posted @ 2020-12-26 09:32  canwinfor  阅读(136)  评论(0)    收藏  举报