差分约束裸题。
和之前不同的是,只要求判环,所以用dfs的spfa,bfs版会T4个点。
各种判环方法:
1.拓扑排序
2.spfa,当某点入队次数>=n;
3.dfs_spfa 正在vis中的某点再次被更新
4.spfa,当入队次数>=某个很大的值。十分玄学,据说这是一种靠rp但是期望很优秀的算法。
//Twenty #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<vector> #include<cmath> #include<queue> typedef long long LL; const int maxn=10005; using namespace std; int n,m,o,l,r,w; namespace fastIO { const int sz=1<<15|1; char ch,buf[sz],*l,*r; void gechar(char &c) { if(l==r) r=(l=buf)+fread(buf,1,sz,stdin); c = l==r?(char)EOF:*l++; } template<typename T> void read(T &x) { int f=1; x=0; gechar(ch); while(ch!='-'&&(ch<'0'||ch>'9')) gechar(ch); if(ch=='-') f=-1,gechar(ch); for(;ch>='0'&&ch<='9';gechar(ch)) x=x*10+ch-'0'; x=x*f; } } int ecnt,fir[maxn],nxt[maxn<<2],to[maxn<<2],val[maxn<<2],cnt[maxn]; void add(int u,int v,int w) { nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w; } void init() { fastIO::read(n); fastIO::read(m); for(int i=1;i<=n;i++) add(0,i,0); for(int i=1;i<=m;i++) { fastIO::read(o); fastIO::read(l); fastIO::read(r); if(o!=3) fastIO::read(w); if(o==1) add(r,l,-w); else if(o==2) add(l,r,w); else add(l,r,0),add(r,l,0); } } int vis[maxn],dis[maxn],fl; queue<int>que; int spfa(int x) { for(int i=fir[x];i;i=nxt[i]) { if(dis[to[i]]>dis[x]+val[i]) { dis[to[i]]=dis[x]+val[i]; if(vis[to[i]]==1) { fl=1; return 0;} vis[to[i]]=1; spfa(to[i]); } } vis[x]=0; } void work() { memset(dis,127,sizeof(dis)); dis[0]=0; vis[0]=1; spfa(0); if(fl) printf("No "); else printf("Yes "); } //#define DEBUG int main() { #ifdef DEBUG freopen("1.in","r",stdin); #endif init(); work(); return 0; }