UVa11090 Going in Cycle!!

来源:互联网 发布:mysql sql delete语句 编辑:程序博客网 时间:2024/06/01 20:50
UVa11090 Going in Cycle!!

 

链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34650

 

【思路】

   二分+SPFA。

   二分平均值mid,如果有平均值小于mid的情况我们就缩小猜测值否则增大猜测值。如何判定?如果有平均值小于mid 则有:w1-mid+w2-mid+w3-mid+…<0 即将各条边权减mid后图中存在负圈,SPFA判负圈即可。

   需要注意把int修改为double

【代码】

 

 1 #include<cstdio> 2 #include<queue> 3 #include<cstring>  4 #include<algorithm> 5 using namespace std; 6  7 const int maxn = 100+10; 8 const double INF=1e10; 9 struct Edge{10     int v,next;11     double w;12 }e[maxn*maxn];13 int en,front[maxn];14 15 int n,m;16 17 inline void AddEdge(int u,int v,double w) {18     en++; e[en].v=v; e[en].w=w; e[en].next=front[u]; front[u]=en;19 }20 21 bool SPFA_NC() {22     int inq[maxn],cnt[maxn];23     double d[maxn];24     queue<int> q;25     memset(cnt,0,sizeof(cnt));26     memset(inq,0,sizeof(inq));27     //添加一个超级源节点 28     for(int s=1;s<=n;s++)29     {30       d[s]=0; inq[s]=1; q.push(s);31     }32     while(!q.empty()) {33         int u=q.front(); q.pop(); inq[u]=0;34         for(int i=front[u];i>=0;i=e[i].next) {35             int v=e[i].v; double w=e[i].w;36             if(d[v]>d[u]+w) {37                 d[v]=d[u]+w;38                 if(!inq[v]) {39                     inq[v]=1;40                     q.push(v);41                     if(++cnt[v]>n+1) return true;42                 }43             }44         }45     }46     return false;47 }48 49 inline void init() {50     en=0;51     memset(front,-1,sizeof(front));52 }53 54 bool can(double x) {55     for(int i=1;i<=en;i++) e[i].w-=x;56     bool ans=SPFA_NC();57     for(int i=1;i<=en;i++) e[i].w+=x;58     return ans;59 }60 61 int main() {62     int T;63     scanf("%d",&T);64     for(int kase=1;kase<=T;kase++) {65         init();66         scanf("%d%d",&n,&m);67         double L=0,R=0;68         int u,v; double w;69         for(int i=0;i<m;i++) {70             scanf("%d%d%lf",&u,&v,&w);71             AddEdge(u,v,w);72             if(w>R) R=w;73         }74         printf("Case #%d: ",kase);75         if(!can(R+1)) printf("No cycle found.\n");76         else 77         {78            while(R-L>1e-3) {79                 double M=L+(R-L)/2;80                 if(can(M)) R=M;  //存在平均值小于mid的回路 则缩小猜测值 81                   else L=M;82            }83            printf("%.2lf\n",L);84         }85     }86     return 0;87 }

 

0 0
原创粉丝点击