【问题描述】
在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,下次注意