题目连接:intervals
题意:
给一个区间[ai,bi],这个区间里有ci个相同的元素,问这个集合最少包含多少元素;
思路:
可以得到这样的几个不等式;
c[i]<=dis[b+1]-dis[a];
0<=dis[i+1]-dis[i];
-1<=dis[i]-dis[i+1];
题意是一定要满足这些条件,那么就是找最长路;当然也可以变成 >= 来建图,求最短路;
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int INF = 2147483647;
const int maxn = 50050;
struct Node{
int ne;
int to;
int w;
}e[maxn<<2];
int head[maxn];
int vis[maxn];
int dis[maxn];
int cnt,n,en,st;
void init(){
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
for(int i=0;i<=n;i++){
dis[i] = -INF;
}
st = INF;
cnt = en = 0;
}
void add(int u,int v,int val){
e[cnt].to = v;
e[cnt].ne = head[u];
e[cnt].w = val;
head[u] = cnt ++;
}
int SPFA(){
queue<int>q;
dis[st] = 0;
vis[st] = 1;
q.push(st);
while(!q.empty()){
int now = q.front();
q.pop();
for(int i=head[now];~i;i=e[i].ne){
int to = e[i].to;
if(dis[to] < dis[now] + e[i].w){
dis[to] = dis[now] + e[i].w;
if(!vis[to]){
vis[to] = 1;
q.push(to);
}
}
}
vis[now] = 0;
}
return dis[en];
}
int main()
{
while(scanf("%d",&n) != EOF){
init();
for(int i=1;i<=n;i++){
int x,y,val;
scanf("%d%d%d",&x,&y,&val);
add(x,y+1,val);
en = max(en,y+1);
st = min(st,x);
}
for(int i=st;i<en;i++){
add(i,i+1,0);
add(i+1,i,-1);
}
printf("%d\n",SPFA());
}
return 0;
}
HDU 3592
include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 10000;
const int INF = 2147483647;
struct Node{
int to;
int ne;
int w;
}e[maxn];
int head[maxn];
int vis[maxn],dis[maxn],num[maxn];
int cnt,T,n,m,k;
void init(){
memset(head,-1,sizeof(head));
for(int i=0;i<=n;i++){
vis[i] = 0;
dis[i] = INF;
num[i] = 0;
}
cnt = 0;
}
void add(int u,int v,int val){
e[cnt].to = v;
e[cnt].ne = head[u];
e[cnt].w = val;
head[u] = cnt ++;
}
int SPFA(){
queue<int>q;
q.push(1);
dis[1] = 0;
vis[1] = 1;
while(!q.empty()){
int now = q.front();
q.pop();
for(int i=head[now];~i;i=e[i].ne){
int to = e[i].to;
if(dis[to] > dis[now] + e[i].w){
dis[to] = dis[now] + e[i].w;
if(!vis[to]){
q.push(to);
if(++num[to] > n )
return -1;
vis[to] = 1;
}
}
}
vis[now] = 0;
}
return dis[n] == INF ? -2 : dis[n];
}
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&k);
init();
int x,y,val;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&val);// y - x <= val
add(x,y,val);
}
for(int i=1;i<=k;i++){
scanf("%d%d%d",&x,&y,&val); // y - x >= val => x - y <= -val
add(y,x,-val);
}
int k = SPFA();
printf("%d\n",k);
}
return 0;
}
题意:有n个屋子,超人从最矮的屋子开始,依次跳下比当前屋子高且最接近当前高度的屋子(即按照屋子高度增序来跳),但超人跳跃还有一个水平距离限制D,他每次跳的水平距离<=D。现在给你每个屋子的高度是它们的相对位置,你不能改变屋子的相对位置,但是可以水平移动屋子,使得最矮的屋子和最高的屋子的水平距离最大。如果无论怎样移动,超人都无法跳到最后那个屋子则输出-1
思路:用一个结构体记录房子的高度以及位置,id存房子的编号,high存房子的高度
建边一:相邻的房子至少距离为1(未排序之前)
建边二:将房子按高度递增排序后,选择 最低房子 和 最高房子中位置较小的为起点,另一个为终点。那么对于相邻的房子,我们可以建一条 位置小的指向位置大的边且权值为D;
(位置相邻的房子距离至少差1,相邻高度的两间房子最多差d来建边)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 1100;
const int INF = 2147483647;
struct Node{
int to;
int ne;
int w;
}e[maxn<<2];
struct N{
int id;
int high;
}str[maxn];
int dis[maxn],vis[maxn],head[maxn],num[maxn];
int cnt ,T,n,d,st,en;
void init(){
cnt = 0;
memset(head,-1,sizeof(head));
}
bool cmp(N a,N b){
return a.high > b.high;
}
void add(int u,int v,int val){
e[cnt].ne = head[u];
e[cnt].to = v;
e[cnt].w = val;
head[u] = cnt ++;
}
void get(){
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++){
scanf("%d",&str[i].high);
str[i].id = i;
}
sort(str+1,str+1+n,cmp);
st = min(str[1].id,str[n].id);
en = max(str[1].id,str[n].id);
for(int i=1;i<=n-1;i++){
if(str[i].id > str[i+1].id){
add(str[i+1].id,str[i].id,d);
}
else {
add(str[i].id,str[i+1].id,d);
}
add(i+1,i,-1);
}
}
void SPFA(){
for(int i=1;i<=n;i++){
dis[i] = INF;
vis[i] = 0;
num[i] = 0;
}
queue<int>q;
vis[st] = 1;
dis[st] = 0;
num[st] = 1;
q.push(st);
while(!q.empty()){
int now = q.front();
q.pop();
for(int i=head[now];~i;i=e[i].ne){
int to = e[i].to;
if(dis[to] > dis[now] + e[i].w){
dis[to] = dis[now] + e[i].w;
if(!vis[to]){
vis[to] = 1;
q.push(to);
if(++num[to] > n){
printf("-1\n");
return ;
}
}
}
}
vis[now] = 0;
}
printf("%d\n",dis[en]);
}
int main(){
scanf("%d",&T);
int k = 1;
while(T--){
init();
get();
printf("Case %d: ",k++);
SPFA();
}
return 0;
}