码迷,mamicode.com
首页 > 其他好文 > 详细

P1993 小K的农场

时间:2020-05-05 00:38:23      阅读:56      评论:0      收藏:0      [点我收藏+]

标签:size   main   mem   节点   代码   超级   算法   def   eof   

题意描述

简单的不能再简单的差分约束裸题啦。(但是我却深感出题人的恶意)

给出一张有 \(n\) 个点的图,以及 \(m\) 对点的数量关系,问是否可以满足每一对关系。

其中一共有三种数量关系:

  1. \(a-b\geq c\)
  2. \(a-b\leq c\)
  3. \(a=b\)

算法分析

差分约束...没什么好讲的了。

  1. \(b-a\leq -c\),即 \(e(a,b)=-c\)
  2. \(a-b\leq c\),即 \(e(b,a)=c\)
  3. \(a-b\leq 0,b-a\leq 0\),即 \(e(a,b)=e(b,a)=0\)

建立完图论模型后,其实还有潜在的数量关系:每个点的点权 \(\geq 0\)

\(a-0\leq 0\),即 \(e(0,a)=0\)

然后再建立一个超级节点 \(n+1\),建立 \(e(n+1,i)=0(0\leq i\leq n)\)

如果有负环就输出 No,否则输出 Yes。(用某已死算法 spfa 即可)

但是写完一交发现 TLE 4个点,深感数据的良心,所以决定优化一番。

首先最后那个 \(e(0,a)=0\) 的那个边其实可以不用建立,因为一旦出现负权情况就会直接 No。

所以再删除 一个节点+n条边 之后时间宽裕了一点,加上 O2 就可以跑过了。

至于没有 O2 的情况...,找一个 spfa 的 dfs 优化好了。

代码实现

主要是建边,然后就是 spfa 裸题了。(记得开 O2)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#define N 20010
using namespace std;

int n,m,head[N],dis[N],sum[N],cnt=0;
bool vis[N];
struct Edge{
	int nxt,to,val;
}ed[N<<1];

int read(){
	int x=0,f=1;char c=getchar();
	while(c<‘0‘ || c>‘9‘) f=(c==‘-‘)?-1:1,c=getchar();
	while(c>=‘0‘ && c<=‘9‘) x=x*10+c-48,c=getchar();
	return x*f;
}

void add(int u,int v,int w){
	ed[++cnt].nxt=head[u];
	ed[cnt].to=v,ed[cnt].val=w;
	head[u]=cnt;
	return;
}

bool spfa(int s){
	queue<int>q;
	memset(dis,0x3f,sizeof(dis));
	memset(vis,false,sizeof(vis));
	memset(sum,0,sizeof(sum));
	dis[s]=0,vis[s]=true;
	q.push(s);
	while(!q.empty()){
		int u=q.front();q.pop();
		vis[u]=false;
		if(++sum[u]>=n) return true; 
		for(int i=head[u];i;i=ed[i].nxt){
			int v=ed[i].to,w=ed[i].val;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				if(!vis[v]) q.push(v),vis[v]=true;
			}
		}
	}
	return false;
}

int main(){
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		int type=read(),u=read(),v=read(),w;
		if(type==1) w=read(),add(u,v,-w);
		else if(type==2) w=read(),add(v,u,w);
		else add(u,v,0),add(v,u,0);
	}
	for(int i=1;i<=n;i++) add(0,i,0);
	if(spfa(0)) puts("No");
	else puts("Yes");
	return 0;
}

完结撒花

P1993 小K的农场

标签:size   main   mem   节点   代码   超级   算法   def   eof   

原文地址:https://www.cnblogs.com/lpf-666/p/12829041.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!