首页 > 代码库 > Bzoj4773 负环
Bzoj4773 负环
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
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 }
为啥会错啊……
非要把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 }
Bzoj4773 负环
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。