码迷,mamicode.com
首页 > 其他好文 > 详细

Bzoj4773 负环

时间:2017-03-28 18:41:23      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:add   stream   cstring   name   close   void   水过   input   ash   

Time Limit: 100 Sec  Memory Limit: 256 MB
Submit: 194  Solved: 97

Description

在忘记考虑负环之后,黎瑟的算法又出错了。对于边带权的有向图 G = (V, E),请找出一个点数最小的环,使得
环上的边权和为负数。保证图中不包含重边和自环。
 
 

 

Input

第1两个整数n, m,表示图的点数和边数。
接下来的m行,每<=三个整数ui, vi, wi,表<=有一条从ui到vi,权值为wi的有向边。
2 <= n <= 300
0 <= m <= n(n <= 1)
1 <= ui, vi <= n
|wi| <= 10^4
 

 

Output

仅一行一个整数,表示点数最小的环上的点数,若图中不存在负环输出0。
 

 

Sample Input

3 6
1 2 -2
2 1 1
2 3 -10
3 2 10
3 1 -10
1 3 10

Sample Output

2

HINT

 

Source

二分答案判负环

用倍增什么的搞一搞就好了。

然而试图用SPFA水过去的时候发现我可能连SPFA都不会写了

 

技术分享
 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 const int mxn=100010;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}
13     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}
14     return x*f;
15 }
16 struct edge{
17     int v,nxt,w;
18 }e[mxn<<1];
19 int hd[mxn],mct=0;
20 void add_edge(int u,int v,int w){
21     e[++mct].v=v;e[mct].nxt=hd[u];e[mct].w=w;hd[u]=mct;return;
22 }
23 int lim;
24 int inq[mxn],dis[mxn];
25 bool SPFA(int u,int time){
26     if(inq[u])return 1;
27     if(time>lim)return 0;
28     inq[u]=1;
29     for(int i=hd[u];i;i=e[i].nxt){
30         int v=e[i].v;
31         if(dis[v]>=dis[u]+e[i].w){
32             dis[v]=dis[u]+e[i].w;
33             if(SPFA(v,time+1))return 1;
34         }
35     }
36     inq[u]=0;
37     return 0;
38 }
39 int n,m;
40 bool chk(){
41     for(int i=1;i<=n;i++){
42         memset(dis,0x3f,sizeof dis);
43         memset(inq,0,sizeof inq);
44         if(SPFA(i,1))return 1;
45     }
46     return 0;
47 }
48 void solve(){
49     int l=1,r=n;
50     int res=0;
51     while(l<=r){
52         int mid=(l+r)>>1;
53         lim=mid;
54         memset(inq,0,sizeof inq);
55         if(chk()){
56             res=mid;
57             r=mid-1;
58         }
59         else l=mid+1;
60     }
61     printf("%d\n",res);
62     return;
63 }
64 int main(){
65     int i,j,u,v,w;
66     n=read();m=read();
67     for(i=1;i<=m;i++){
68         u=read();v=read();w=read();
69         add_edge(u,v,w);
70     }
71     solve();
72     return 0;
73 }
WA

为啥会错啊……

 

非要把inq放在循环里面才能过……

——————updated

仔细想想好像确实是这样,起初的u并没有被更新过就直接入队,会导致不必要的错误。

但是循环枚举起点的时候把dis[i]设成0,也过不了,无限TLE。

大概理解还是不透彻

——————

技术分享
 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 const int mxn=310;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}
13     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}
14     return x*f;
15 }
16 struct edge{
17     int v,nxt,w;
18 }e[mxn*mxn];
19 int hd[mxn],mct=0;
20 void add_edge(int u,int v,int w){
21     e[++mct].v=v;e[mct].nxt=hd[u];e[mct].w=w;hd[u]=mct;return;
22 }
23 int lim;
24 int inq[mxn],dis[mxn];
25 bool SPFA(int u,int time){
26     for(int i=hd[u];i;i=e[i].nxt){
27         int v=e[i].v;
28         if(dis[v]>=dis[u]+e[i].w){
29             if(inq[v])return 1;
30             if(time==lim)return 0;
31             dis[v]=dis[u]+e[i].w;
32             inq[v]=1;
33             if(SPFA(v,time+1))return 1;
34             inq[v]=0;
35         }
36     }
37     return 0;
38 }
39 int n,m;
40 bool chk(){
41     for(int i=1;i<=n;i++){
42         memset(dis,0,sizeof dis);
43         memset(inq,0,sizeof inq);
44         dis[i]=0;inq[i]=1;
45         if(SPFA(i,1))return 1;
46     }
47     return 0;
48 }
49 void solve(){
50     int l=1,r=n;
51     int res=0;
52     while(l<=r){
53         int mid=(l+r)>>1;
54         lim=mid;
55         memset(inq,0,sizeof inq);
56         if(chk()){
57             res=mid;
58             r=mid-1;
59         }
60         else l=mid+1;
61     }
62     printf("%d\n",res);
63     return;
64 }
65 int main(){
66     int i,j,u,v,w;
67     n=read();m=read();
68     for(i=1;i<=m;i++){
69         u=read();v=read();w=read();
70         add_edge(u,v,w);
71     }
72     solve();
73     return 0;
74 }
AC

 

Bzoj4773 负环

标签:add   stream   cstring   name   close   void   水过   input   ash   

原文地址:http://www.cnblogs.com/SilverNebula/p/6636177.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!