luogu P3084 [USACO13OPEN]照片Photo

题目传送门:https://www.luogu.org/problemnew/show/P3084

 

 

题意:

有n头奶牛,m张照片,每张照片都覆盖了连续一段奶牛,且每张照片中都有至少一头斑点奶牛,但是这些照片不一定把每一头奶牛都拍了进去。求至少有多少只斑点奶牛,若无解,输出-1。

 

 

思路:

由题意可知:

1.每一个区间最多一头奶牛

2.每一个区间最少一头奶牛

 

我们可以得到:

1.  0a[i]-a[i-1]≤1(每一头相邻的奶牛有且仅有一头斑点奶牛)

2.  0a[y]-a[x-1]≤1(每一个区间——被找到的区间,有且仅有一头斑点奶牛)

 

可变形为:

1.  a[i]-a[i-1]≤1

2.  a[y]-a[x-1]≤1

 

然后我们可以发现:这两条式子满足差分约束系统。

 

我们就可以建边了:

1.i-1向i建一条长度为1的边,i向i-1建一条长度为0的边

2.x-1向y建一条长度为1的边,y向x-1建一条长度为-1的边

最后就跑最短路即可。

 

 

代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define I inline
#define R register
#define INF 1000000
using namespace std;
deque<int> f;
	int n,m,k,len=0,tot=0;
	int p[400010],last[400010];
	struct node{int x,y,z,next;} a[800010];
	int dis[400010],q[400010];
	bool bz[400010];
I int readint()
{
	int f=1,x=0;
	char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())
		if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';x=(x<<3)+(x<<1)+(ch^48),ch=getchar());
	return x*f;
}
I void ins(int x,int y,int z)
{
	a[++len].x=x;a[len].y=y;a[len].z=z;a[len].next=last[x];last[x]=len;
}
I int spfa()
{
	for(int i=1;i<=n;i++)
		dis[i]=1e7;
	dis[0]=0;
	f.push_back(0);
	while(!f.empty())
	{
		int x=f.front();
		f.pop_front();
		bz[x]=false;
		for(R int i=last[x];i;i=a[i].next)
		{
			int y=a[i].y;
			if(dis[x]+a[i].z<dis[y])
			{
				dis[y]=dis[x]+a[i].z;
				if(!bz[y])
				{
					if(++tot>=INF) return -1;//判负环,不是正确的,只是题目卡差分约束,普通的过不了,只好“特判”
					bz[y]=true;
					if(!f.empty()&&dis[y]<dis[f.front()]) f.push_front(y); else f.push_back(y);
				}
			}
		}
	}
	return dis[n];
}
int main()
{
	int x,y;
	n=readint(),m=readint();
	for(R int i=1;i<=m;i++)
	{
		x=readint(),y=readint();
		ins(x-1,y,1),ins(y,x-1,-1);
	}
	for(R int i=1;i<=n;i++)
		ins(i-1,i,1),ins(i,i-1,0);
	printf("%d",spfa());
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值