spfa+差分约束系统(D - POJ - 1201 && E - POJ - 1364&&G - POJ - 1)+建边的注意事项+超级源点的建立
题目链接:https://cn.vjudge.net/contest/276233#problem/D
给出n个闭合的整数区间[ai,bi]和n个整数c1,…,cn。
编写一个程序:
从标准输入中读取间隔数,它们的端点和整数c1,…,cn,
计算具有间隔[ai,bi]的至少ci共同元素的整数集合Z的最小尺寸,对于每个i = 1,2,…,n,
具体思路:首先,我们假设存在一个数组s,s[i]记录的是第i个点到第0个点的需要取出的点的个数,对于题目中的从(A,B)至少有d个,我们就可以将这个条件变成posB-(posA-1)>=d,也就是(posA-1)-posB<=-d,这一段的边就建立好了,但是对于这个区间内的每一个数,我们的范围是没有限制的,但是如果没有限制会出现下列情况,s[i]>=i,也就是说会出现矛盾,所以对于这个区间内的没一个数都需要限制,也就是对于区间(i,i+1),我们可以引申出如下条件。0=<pos(i+1)-pos(i)<=1,
也就是 pos[i+1]-pos[i]>=0(pos[i]-pos[i+1]<=0),和 pos[i+1]-pos[i]<=1,也就是把这段区间的每一个小的区间的条件设立好了就可以了。(注意建边的时候注意方向)
AC代码:
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = +;
const int maxedge= +;
int num,head[maxn];
int dis[maxn],vis[maxn];
int minx=inf;
int maxy=;
struct node
{
int fr;
int to;
int cost;
int nex;
} edge[maxedge];
struct point
{
int st;
int ed;
} po[maxn];
void init()
{
for(int i=; i<=; i++)
{
head[i]=-;
vis[i]=;
dis[i]=inf;
}
num=;
}
void addedge(int fr,int to,int cost)
{
edge[num].to=to;
edge[num].cost=cost;
edge[num].nex=head[fr];
head[fr]=num++;
}
ll spfa(int st,int ed)
{
dis[st]=;
vis[st]=;
queue<int>q;
q.push(st);
while(!q.empty())
{
int tmp=q.front();
q.pop();
vis[tmp]=;
for(int i=head[tmp]; i!=-; i=edge[i].nex)
{
int u=edge[i].to;
if(dis[u]>dis[tmp]+edge[i].cost)
{
dis[u]=dis[tmp]+edge[i].cost;
if(vis[u])
continue;
vis[u]=;
q.push(u);
}
}
}
return dis[ed];
}
int main()
{
int n,d;
scanf("%d",&n);
init();
for(int i=; i<=n; i++)
{
scanf("%d %d %d",&po[i].st,&po[i].ed,&d);
addedge(po[i].st-+,po[i].ed+,-d);//两个左边都+1,是为了防止出现变成-1的情况。
minx=min(minx,po[i].st);
maxy=max(maxy,po[i].ed+);
}
for(int i=minx; i<=maxy-; i++)
{
addedge(i,i+,);
addedge(i+,i,);
}
int ans=spfa(minx,maxy);
printf("%d\n",-ans);
return ;
}
E:
n个数的一个序列,m个约数,si, ni, oi, ki, 代表了序列中第si个数到第si+ni个数的和大于或小于ki,gt = 大于,lt = 小于
问是否存在相悖的约束
一个由memset引发的惨案,,,本来是用for循环初始化来着,结果这个题用for一直wa(后来发现是越界了--),然后改成memset的化就给过了。但是顺便加深了对建图的理解(理解写在上面了)。
AC代码:
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = +;
const int maxedge= +;
int num,head[maxn],out[maxn];
int dis[maxn],vis[maxn];
int n,m;
struct node
{
int fr;
int to;
int cost;
int nex;
} edge[maxedge];
struct point
{
int st;
int ed;
} po[maxn];
void init()
{
for(int i=; i<maxn; i++)
{
vis[i]=;
dis[i]=inf;
head[i]=-;
out[i]=;
}
num=;
num=;
}
void addedge(int fr,int to,int cost)
{
edge[num].to=to;
edge[num].cost=cost;
edge[num].nex=head[fr];
head[fr]=num++;
}
ll spfa(int st)
{
dis[st]=;
vis[st]=;
queue<int>q;
q.push(st);
while(!q.empty())
{
int tmp=q.front();
q.pop();
if(++out[tmp]>n+)
return -;
vis[tmp]=;
for(int i=head[tmp]; i!=-; i=edge[i].nex)
{
int u=edge[i].to;
if(dis[u]>dis[tmp]+edge[i].cost)
{
dis[u]=dis[tmp]+edge[i].cost;
if(vis[u])
continue;
vis[u]=;
q.push(u);
}
}
}
return ;
}
int main()
{
while(cin>>n)
{
init();
if(n==)
break;
cin>>m;
int u,v,d;
string str;
for(int i=; i<=m; i++)
{
cin>>u>>v>>str>>d;
if(str=="gt")
{
addedge(u,u+v+,-(d+));
}
else
{
addedge(v+u+,u,d-);
}
}
for(int i=; i<=n+; i++)
{
addedge(,i,);//超级源点的建立过程
}
int ans=spfa();
if(ans==-)
cout<<"successful conspiracy"<<endl;
else
cout<<"lamentable kingdom"<<endl;
}
return ;
}
G题:
给出数轴上的n个闭合int型区间。现在要在数轴上任意取一堆元素,构成一个元素集合V,要求给出的每个区间和元素集合V的交集至少有两个不同的元素,求集合V最小的元素个数。
超级源点的建立,为了保证整个区间的连通的,我们就需要建立一个超级源点来使得整个图是连通的,但是注意一点,在正常建边的时候,如果是大的指向小的,这个时候我们建立超级源点的时候就也应该遵循这个原则,如果是是小的指向大的,我们建立超级源点的时候反过来就可以了。
AC代码:
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = +;
const int maxnedge=+;
struct node
{
int nex;
int to;
int cost;
} edge[maxnedge];
int head[maxn],vis[maxn],dis[maxn],num;
void init()
{
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
memset(dis,inf,sizeof(dis));
num=;
}
void addedge(int fr,int to,int cost)
{
edge[num].to=to;
edge[num].nex=head[fr];
edge[num].cost=cost;
head[fr]=num++;
}
int spfa(int st,int ed)
{
queue<int>q;
dis[st]=;
vis[st]=;
q.push(st);
while(!q.empty())
{
int tmp=q.front();
q.pop();
vis[tmp]=;
for(int i=head[tmp]; i!=-; i=edge[i].nex)
{
int u=edge[i].to;
if(dis[u]>dis[tmp]+edge[i].cost)
{
dis[u]=dis[tmp]+edge[i].cost;
if(vis[u])
continue;
vis[u]=;
q.push(u);
}
}
}
return dis[ed];
}
int main()
{
init();
int n;
scanf("%d",&n);
int u,v;
int minx=inf,maxy=;
for(int i=; i<=n; i++)
{
scanf("%d %d",&u,&v);
u+=;
v+=;
addedge(u-,v,-);
addedge(v,u-,v-u+);
minx=min(minx,u-);
maxy=max(maxy,v);
}
int st=maxy+;
for(int i=minx; i<maxy; i++){
addedge(st,i,);
addedge(i,i+,);
addedge(i+,i,);
}
addedge(st,maxy,);
int ans=spfa(st,maxy);
printf("%d\n",-ans);
return ;
}
spfa+差分约束系统(D - POJ - 1201 && E - POJ - 1364&&G - POJ - 1)+建边的注意事项+超级源点的建立的更多相关文章
- spfa+差分约束系统(C - House Man HDU - 3440 )+对差分约束系统的初步理解
题目链接:https://cn.vjudge.net/contest/276233#problem/C 题目大意:有n层楼,给你每个楼的高度,和这个人单次的最大跳跃距离m,两个楼之间的距离最小是1,但 ...
- poj 1364 King(线性差分约束+超级源点+spfa判负环)
King Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14791 Accepted: 5226 Description ...
- UVA 11374 Halum (差分约束系统,最短路)
题意:给定一个带权有向图,每次你可以选择一个结点v 和整数d ,把所有以v为终点的边权值减少d,把所有以v为起点的边权值增加d,最后要让所有的边权值为正,且尽量大.若无解,输出结果.若可无限大,输出结 ...
- 差分约束系统专题 && 对差分约束系统的理解
具体能解决的问题: 求最长路,最短路,或者判断解是否存在. 在建边的时候: 一般是给你区间减法的关系,或者是这个点到另一个点的关系.如果给你的关系是除法的话,我们可以通过使用两边同时取log的方式,将 ...
- 【POJ 1201】 Intervals(差分约束系统)
[POJ 1201] Intervals(差分约束系统) 11 1716的升级版 把原本固定的边权改为不固定. Intervals Time Limit: 2000MS Memory Limit: ...
- 差分约束系统 + spfa(A - Layout POJ - 3169)
题目链接:https://cn.vjudge.net/contest/276233#problem/A 差分约束系统,假设当前有三个不等式 x- y <=t1 y-z<=t2 x-z< ...
- poj 1201 Intervals(差分约束)
做的第一道差分约束的题目,思考了一天,终于把差分约束弄懂了O(∩_∩)O哈哈~ 题意(略坑):三元组{ai,bi,ci},表示区间[ai,bi]上至少要有ci个数字相同,其实就是说,在区间[0,500 ...
- POJ 3169 Layout (spfa+差分约束)
题目链接:http://poj.org/problem?id=3169 差分约束的解释:http://www.cnblogs.com/void/archive/2011/08/26/2153928.h ...
- POJ 3159 Candies (图论,差分约束系统,最短路)
POJ 3159 Candies (图论,差分约束系统,最短路) Description During the kindergarten days, flymouse was the monitor ...
随机推荐
- QtCreator源码分析—2.启动主程序(4篇)
QtCreator采用插件体系结构.主程序启动插件管理器(PluginManager),再通过插件管理器加载其插件,QtCreator的所有功能均使用插件实现. 我们先来分析主程序对插件管理器的主要操 ...
- C 语言assert使用
1.assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:#include <assert.h>void assert( i ...
- 【转载】JSP生成静态Html页面
在网站项目中,为了访问速度加快,为了方便百度爬虫抓取网页的内容,需要把jsp的动态页面转为html静态页面.通常有2种常用的方式: 1.伪静态,使用URL Rewriter 2.纯静态,本文中代码实现 ...
- C++ STL 常用算术和生成算法
C++ STL 常用算术和生成算法 accumulate() accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值. #include<numeric> ...
- IbatisNet连接oracle 报错
提示什么 connect oracle 1.5.0.xxxx 将你本机的oracle 客户端版本重装换成32位即可
- DPHARD
此篇收集各类DP题. <1D1D动态规划优化初步>的3个模型 1. f[x] = min(f[i]+w[i, x]), i < x且w[i, x]满足单调性(即w[i, j]+w[i ...
- 【BZOJ3609】人人尽说江南好(博弈论)
[BZOJ3609]人人尽说江南好(博弈论) 题面 BZOJ 洛谷 题解 昨天考试的时候,毒瘤出题人出了一个\(noip\)博弈十合一然后他就被阿鲁巴了,因为画面残忍,就不再展开. 这题是他的十合一中 ...
- BZOJ4727 [POI2017]Turysta 【竞赛图哈密顿路径/回路】
题目链接 BZOJ4727 题解 前置芝士 1.竞赛图存在哈密顿路径 2.竞赛图存在哈密顿回路,当且仅当它是强联通的 所以我们将图缩点后,拓扑排序后一定是一条链,且之前的块内的点和之后块内的点的边一定 ...
- Gradle 命令之 --stacktrace , --info , --debug 用法
FAQ: Android studio 出现错误Run with --stacktrace option to get the stack trace. Run with --info or --de ...
- 解题:CQOI 2017 老C的方块
题面 看起来很像网络流的二分图套路题,然后我们大力观察(题目定义的相邻我用引号括起来,应该能看懂) 发现“相邻”的一对方格如果各自连着一个一个方格就gg了,于是对于所有这些“相邻”的方格,我们有两种选 ...