【bzoj3373】[Usaco2004 Mar]Lying Livestock 说谎的牲畜 差分约束

就当是我刚学差分约束吧,最裸的题目。

枚举每一头牛,然后反向!!!这头牛说的边,跑最短路,如果没有负环,那么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;
}



你可能感兴趣的:(【bzoj3373】[Usaco2004 Mar]Lying Livestock 说谎的牲畜 差分约束)