就当是我刚学差分约束吧,最裸的题目。
枚举每一头牛,然后反向!!!这头牛说的边,跑最短路,如果没有负环,那么ans++
如果i大于j,那么xi>=xj+1,即xi-1>=xj,所以i向j连一条边权为-1的边。
注意,说谎,是要反向,而不是去掉!!!
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 200100 using namespace std; struct yts { int a,b,c; }e[maxn]; int next[maxn],head[maxn],to[maxn],len[maxn],dis[maxn]; bool vis[maxn],flag; int n,m,num,ans; void addedge(int x,int y,int z) { num++;to[num]=y;len[num]=z;next[num]=head[x];head[x]=num; } void build(int x) { memset(head,0,sizeof(head)); num=0; for (int i=1;i<=m;i++) if (e[i].a!=x) addedge(e[i].b,e[i].c,-1); else addedge(e[i].c,e[i].b,0); } void dfs(int x) { vis[x]=1; for (int p=head[x];p;p=next[p]) if (dis[x]+len[p]<dis[to[p]]) { if (vis[to[p]]) {flag=1;return;} dis[to[p]]=dis[x]+len[p]; dfs(to[p]); } vis[x]=0; } bool check() { flag=0; memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); for (int i=1;i<=n;i++) { dfs(i); if (flag) return 1; } return 0; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c); for (int i=1;i<=n;i++) { build(i); if (!check()) ans++; } printf("%d\n",ans); return 0; }