能把差分约束卡死的题,因为正解并不是差分约束,然而被我用一种奇怪的姿势过去了。。。
差分约束就是相等互相连零边,不超过/不低于从不多的一方向另一方连零边,超过/低于从少的一方向另一方连最小的边权——$1$,最后跑最长路。然后你会发现你被卡T了若干个点,于是开始了优化=。=
首先有一个通用的优化:去掉超级源点,改为把每个点的距离手动赋值为$1$+入队,发现好像并不能过
然而出题人的数据造水了,只需要判断有没有小于/大于自己的即可过掉绝大部分点。。。
1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int N=100005; 8 int p[N],noww[2*N],goal[2*N],val[2*N]; 9 int vis[N],inq[N],dis[N]; 10 int n,k,t1,t2,t3,cnt; 11 long long ans; 12 queue<int> qs; 13 inline int read() 14 { 15 int ret=0; 16 char ch=getchar(); 17 while(!isdigit(ch)) 18 ch=getchar(); 19 while(isdigit(ch)) 20 ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar(); 21 return ret; 22 } 23 inline void link(int f,int t,int v) 24 { 25 noww[++cnt]=p[f],p[f]=cnt; 26 goal[cnt]=t,val[cnt]=v; 27 } 28 void SBData() 29 { 30 if((t1==2||t1==4)&&t2==t3) 31 {printf("-1"); exit(0);} 32 } 33 int main () 34 { 35 register int i; 36 n=read(),k=read(); 37 for(i=1;i<=k;i++) 38 { 39 t1=read(),t2=read(),t3=read(); 40 if(t1==1) link(t2,t3,0),link(t3,t2,0); 41 else if(t1==2) link(t2,t3,1); 42 else if(t1==3) link(t3,t2,0); 43 else if(t1==4) link(t3,t2,1); 44 else link(t2,t3,0); SBData(); 45 } 46 for(i=1;i<=n;i++) 47 qs.push(i),dis[i]=vis[i]=1,inq[i]=true; 48 while(!qs.empty()) 49 { 50 int tn=qs.front(); 51 qs.pop(),inq[tn]=false; 52 for(i=p[tn];i;i=noww[i]) 53 if(dis[goal[i]]<dis[tn]+val[i]) 54 { 55 dis[goal[i]]=dis[tn]+val[i]; 56 if(!inq[goal[i]]) 57 { 58 if(++vis[goal[i]]>n) {printf("-1"); return 0;} 59 qs.push(goal[i]),inq[goal[i]]=true; 60 } 61 } 62 } 63 for(i=1;i<=n;i++) ans+=dis[i]; 64 printf("%lld",ans); 65 return 0; 66 }