bzoj2330 SCOI2011糖果 查分约束系统

坑爹数据= =

一道很弱的查分约束,根据题意连边就好惹,然而添加超级源点会RE= =(一直RE看了下discuss发现段神T了一个钟就是因为这个= =),用priorityqueue优化SPFA会无限超时= =

其实感觉用tarjan判环然后在拓扑图上递推能跑的很快的有空试下

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<bitset>
#include<queue>
#define LL long long
#define ps(x,y) q.push(hhx(x,y))
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;i>=b;i--)
#define efo(i,x) for(int i=last[x];i!=0;i=e[i].next)
using namespace std;
LL read()
{
	LL d=0,f=1;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
	return d*f;
}
#define N 100005
#define S 100001
#define inf 1000000007
struct hhx
{
	int x,dis;
	hhx(int a,int b):dis(b),x(a){}
};
struct edge
{
	int y,c,next;
}e[N*2];
int last[N],ne=0;
int relax[N],dis[N];
int n,m;

void add(int x,int y,int c)
{
	e[++ne].y=y;e[ne].c=c;e[ne].next=last[x];last[x]=ne;
}

queue<hhx>q;
bool spfa()
{
	memset(relax,0,sizeof(relax));
	bitset<N+5>inq;inq.reset();
	inq[S]=1;
	fo(i,1,n)
	{
		dis[i]=1;
		ps(i,1);
	}
	while(!q.empty())
	{
		hhx now=q.front();
		q.pop();
		inq[now.x]=0;
		efo(i,now.x)	
		if(dis[now.x]+e[i].c>dis[e[i].y])
		{
//			cout<<now.x<<' '<<e[i].y<<' '<<dis[now.x]<<' '<<e[i].c<<' '<<dis[e[i].y]<<endl;
			dis[e[i].y]=dis[now.x]+e[i].c;
			if(++relax[e[i].y]>=n)return 0;
			if(inq[e[i].y]==0)
			{
				ps(e[i].y,dis[e[i].y]);
				inq[e[i].y]=1;
			}
		}
	}
	return 1;
}

int main()
{
	scanf("%d%d",&n,&m);
	fo(i,1,m)
	{
		int k,x,y;scanf("%d%d%d",&k,&x,&y);
		if(k==1){add(x,y,0);add(y,x,0);continue;}
		if(k==2)
		{
			if(x==y)
			{
				puts("-1");
				return 0;
			}
			add(x,y,1);
			continue;
		}
		if(k==3){add(y,x,0);continue;}
		if(k==4)
		{
			if(x==y)
			{
				puts("-1");
				return 0;
			}
			add(y,x,1);
			continue;
		}
		if(k==5){add(x,y,0);continue;}
	}
	if(!spfa())puts("-1");
	else
	{
		LL ans=0;
		fo(i,1,n)ans+=dis[i];
		printf("%lld\n",ans);
	}
	return 0;
}


你可能感兴趣的:(bzoj2330 SCOI2011糖果 查分约束系统)