种树 差分约束|贪心

2019-04-18 15:29:13 浏览数 (1)

 先看贪心版本。

每次种的树在重叠区间越多,种的树越少。只有结束位置才会重合,就对区间结束的位置从小到大排序。

然后遍历每个区间统计第i个区间种了k个树,若k大于 t ,则continue, 否则从区间末尾往前种树。 

代码语言:javascript复制
//贪心种树 
#include <bits/stdc  .h>
using namespace std;
struct N{
	int s,t,e;
	bool operator < (const N b)const {
		return e<b.e;
	}
};
N node[30005];
int book[30005];
int n,m;
int main()
{
	scanf("%d",&n);
	scanf("%d",&m);
	for(int i=0;i<m;i  ){
		scanf("%d %d %d",&node[i].s,&node[i].e,&node[i].t);
	}
	sort(node,node m);
	int ans=0;
	for(int i =0;i<m;i  ){
		int k = 0;
		for(int j = node[i].s;j<=node[i].e;j  )if(book[j])k  ;
		if(k>=node[i].t)continue;
		for(int j=node[i].e;j>=node[i].s;j--){
			if(!book[j]){
				book[j]=1;
				k  ; ans  ;
				if(k>=node[i].t)break;
			}
		}
	}
	printf("%dn",ans);
	return 0;
 } 

差分约束

题目中有这么几个约束条件

sum[i]是 i 的前缀和。

从u到v: sum[u-1] - sum[v] <= - t

从i-1到i:   sum[i] - sum[i-1] <=1  

从i到i-1:   sum[i-1] - sum[ i ]<=0

最后找一个源点也即N 1,N 1到每个点距离为0   sum[i] - sum[N 1]=0

代码语言:javascript复制
//差分种树 
#include <bits/stdc  .h>
using namespace std;
#define INF 0x7fffffff
#define R register
struct N{
	int v,nxt,w;
};
int cnt,n,m;
int S;
N edge[100005];
int head[100005],dis[30005],book[30005];
int read(){
	int x=0,dign=1;
	char c = getchar();
	while(c<'0'||c>'9'){
		if(c=='-')dign=-1;
		c = getchar();
	}
	while(c>='0'&&c<='9'){
		x = x*10   c - '0';
		c = getchar();
	}
	return x*dign;
}
void add(int u,int v,int w){
	cnt  ;
	edge[cnt].v = v;
	edge[cnt].w = w;
	edge[cnt].nxt = head[u];
	head[u] = cnt;
}
void spfa(){
	queue<int> q;
	for(R int i=0;i<=n 1;i  )dis[i] = INF;
	dis[S] = 0; book[S] = 1; q.push(S);
	while(!q.empty()){
		int u = q.front(); book[u] = 0; q.pop();
		for(R int v,w,i = head[u];i;i=edge[i].nxt){
			v = edge[i].v; w = dis[u]   edge[i].w;
			if(dis[v]>w){
				dis[v] = w;
				if(!book[v]){
					book[v]=1; q.push(v);
				}
			} 
		}
	}
}
int main()
{
	n = read();
	m = read();
	for(R int i=0;i<m;i  ){
		int u,v,w;
		u = read(); v = read(); w = read();
		add(v,u-1,-w);
	}
	for(R int i=1;i<=n;i  ){
		add(i,i-1,0);
		add(i-1,i,1);
	}
	for(R int i=0;i<=n;i  )add(n 1,i,0);
	
	S = n 1;
	
	spfa();
	int mi = INF;
	for(int i=0;i<=n;i  )mi = min(mi,dis[i]);
	printf("%dn",dis[n]-mi);
	return 0;
 } 

0 人点赞