这要是碰上现场赛我得被搞死 从RE到TLE到WA已疯。。
这题建图没有那么直接,通过给出的不等式关系一时想不到怎么建图
所以要对题目给的条件一定程度化简,将不等式两边取对数化简得到Sa-Sb<=c的形式
要注意w取double类型
其次,这题卡时间,根据经验加剪枝:
1、出队次数>sqrt(n)则判断有负环
2、统计总的入队次数,>2n则判断有负环
一般情况下不用这个,因为不严谨
下面两个spfa都是对的,手写队列稍快一点,上面第二个剪枝效果明显
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> using namespace std; struct node { int v; double w; int next; }e[360010]; int n,m,h,head[810],inq[810],outq[810],q[50000]; double d[805]; void addedge(int a,int b,double c) { e[h].v=b; e[h].w=c; e[h].next=head[a]; head[a]=h++; } bool spfa(int s) { int iq,i,top,k; for(i=0;i<=n;i++) d[i]=1000000000; memset(inq,0,sizeof inq); memset(outq,0,sizeof outq); d[s]=0;inq[s]=1; iq=0;i=0; q[iq++]=s; while(i!=iq) { top=q[i]; inq[top]=0; outq[top]++; if(outq[top]>(int)sqrt(n*1.0)) return 0; k=head[top]; while(k>=0) { if(d[e[k].v]-e[k].w>d[top]) { d[e[k].v]=e[k].w+d[top]; if(!inq[e[k].v]) { inq[e[k].v]=1; q[iq++]=e[k].v; } } k=e[k].next; } i++; } return 1; } int spfa(int st)//邻接表 STL { for(int i=0;i<=n;i++) d[i]=100000000; memset(inq,0,sizeof inq); memset(outq,0,sizeof outq); d[st]=0;inq[st]=1; queue<int> q; q.push(st); int cnt=1; while(!q.empty()) { int x=q.front(); q.pop(); inq[x]=0; outq[x]++; if(outq[x]>sqrt(n*1.0)+10) return 0; for(int i=head[x];i!=-1;i=e[i].next) { if(d[e[i].v]>d[x]+e[i].w) { d[e[i].v]=d[x]+e[i].w; if(!inq[e[i].v]) { cnt++; if(cnt>((n+m)*2)) return 0; inq[e[i].v]=1; q.push(e[i].v); } } } } return 1; } int main() { double x,ll,uu,l,u; int i,j; while(~scanf("%d%d%lf%lf",&n,&m,&l,&u)) { memset(head,-1,sizeof head); h=0; ll=log(l);uu=log(u); for(i=0;i<n;i++) for(j=0;j<m;j++) { scanf("%lf",&x); addedge(i,j+n,log(x)-ll); addedge(j+n,i,uu-log(x)); } n+=m;m+=m; if(spfa(0)) printf("YES\n"); else printf("NO\n"); } return 0; }
hdu3666 THE MATRIX PROBLEM --- 差分约束
时间: 2024-10-12 15:48:59