SDOJ 2726 食堂

【问题描述】

    在SD食堂,所有的座位是一行一行的排列。现在有N个座位排成一行,依次编号1,2,…,N,每个座位只能坐一个人,现在L想数一下有多少个人坐着,一个一个数太慢了,L决定只选择M段连续的座位,对每段分别数出人数。由于食堂噪音十分嘈杂,L无法专心,可能有输错了。但是L认为没有数漏,最多是重复计数导致的。现在他把得到的数据给你,希望你帮他算出,一共最多有多少人。

【输入格式】

    第一行2个整数N,M,分别是座位数量,和L分成M段。

    接下来M行,每行3个整数,l,r,k,表示L数了l到r这一段的座位,他数出的结果是k。

【输出格式】

    数出一行一个整数表示答案。

【输入样例】

4 2
1 2 1 
2 4 2

【输出样例】

3

这道题就是很裸的一道差分约束,对于每一个l,r,k,在图上建一条l-1-r的边权为k的边,最后跑一遍SPFA即可。

贴代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+1;
const int MAXM=5e5+1;
const int INF=0x3f3f3f3f;

int dis[MAXN];
int head[MAXM],nxt[MAXM],to[MAXM],w[MAXM],vis[MAXN];
int n,m,k,cnt,st;
queue<int> q;

int Read()               //读入优化,不加会神奇的被卡掉
{
	int i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

void add(int a,int b,int c)
{
	cnt++;
	nxt[cnt]=head[a];
	head[a]=cnt;
	to[cnt]=b;
	w[cnt]=c;
}

void spfa()
{
	memset(dis,INF,sizeof(dis));
	dis[st]=0;
	q.push(st);
	vis[st]=1;
	while(!q.empty())
	{
		int u=q.front();
		vis[u]=0;
		q.pop();
		for(int i=head[u];i;i=nxt[i])
		{
			int v=to[i];
			if(dis[v]>dis[u]+w[i])
			{
				dis[v]=dis[u]+w[i];
				if(!vis[v])
				{
					q.push(v);
					vis[v]=1;
				} 
			}
		}
	}
}

int main()
{
	st=0;
	n=Read(),k=Read();
	for(int i=1;i<=n;++i)
	  add(i,i-1,0),add(i-1,i,1);       //第i个到第i+1个最多可以有一个。
	for(int i=1;i<=k;++i)
	{
		int l=Read(),r=Read(),val=Read();
		add(l-1,r,val);
	}
	spfa();
	cout<<dis[n];                      //结果就是1-n的最短路径
	return 0;
}

小结:memset这个函数感觉会耗用较长时间,一开始我将head和nxt赋为-1,结果爆TLE,去掉就过了……emmm,下次注意

猜你喜欢

转载自blog.csdn.net/g21glf/article/details/81287908