不知这几天种的那好几棵线段树成活了没……
一本通1496:
题意:
在郊区有 NN 座通信基站,PP 条双向电缆,第 ii 条电缆连接基站 AiAi和 BiBi 。特别地,11 号基站是通信公司的总站,NN 号基站位于一座农场中。现在,农场主希望对通信线路进行升级,其中升级第 ii 条电缆需要花费 LiLi 。
电话公司正在举行优惠活动。农场主可以指定一条从 11 号基站到 NN 号基站的路径,并指定路径上不超过 KK 条电缆,由电话公司免费提供升级服务。农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。求至少用多少钱能完成升级。
一句话题意:在加权无向图上求出一条从 11 号结点到 NN 号结点的路径,使路径上第 K+1K+1 大的边权尽量小。
思路:满足单调性,所以用二分,把大于mid的边权设为1,小于mid的边权设为0,跑一遍最短路,看看d[n]是否即可,总体挺水的……
//By hpwwzyy2012
#include
using namespace std;
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
bool f=0;char c=0;int x=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
const int N=1010;
const int M=2020;
struct node{
int next,to,w;
}e[M<<1];int h[N],tot;
struct Bian{
int a,b,w;
void reading(){
a=read();b=read();w=read();
}
}f[M];
inline void add_edge_in_e(int a,int b,int w){
e[++tot]=(node){h[a],b,w};h[a]=tot;
e[++tot]=(node){h[b],a,w};h[b]=tot;
}
const int inf=0x3f3f3f3f;
int d[N],n,p,k;bool v[N];
inline void make_a_map(int mid){
tot=0;memset(h,0,sizeof(h));
for(int i=1;i<=p;i++){
if (f[i].w>mid) add_edge_in_e(f[i].a,f[i].b,1);
else add_edge_in_e(f[i].a,f[i].b,0);
}
return;//重新建边,注意内存循环利用(即tot=0)
}
inline bool check(int mid){
make_a_map(mid);
for(int i=1;i<=n;i++){
d[i]=inf;v[i]=true;
}
d[1]=0;v[1]=false;
queue q;q.push(1);
do{
int z=q.front();q.pop();v[z]=true;
for(int i=h[z];i;i=e[i].next){
register int to=e[i].to;
if (d[to]>d[z]+e[i].w){
d[to]=d[z]+e[i].w;
if (v[to]==true){
v[to]=false;
q.push(to);
}
}
}
}while (q.size());
return d[n]<=k;
}
//用spfa跑最短路
int l,r,mid,ans,i;
int main(){
// freopen("t1.in","r",stdin);
n=read();p=read();k=read();
for(i=1;i<=p;i++)
f[i].reading();
r=-inf;ans=-1;
for(i=1;i<=p;i++){
// l=min(l,f[i].w);
r=max(r,f[i].w);
}
// if (!check(r)){
// printf("-1");
// return 0;
// }
while (l<=r){
mid=(l+r)>>1;
if (check(mid)){
ans=mid;r=mid-1;
}
else l=mid+1;
}
printf("%d",ans);
return 0;
}
一本通1512:
题意:
当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些。FJ 有 NN 头奶牛,编号从 11 到 NN,沿一条直线站着等候喂食。奶牛排在队伍中的顺序和它们的编号是相同的。因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上。即使说,如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标。一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数 LL。另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数 DD。
给出 MLML 条关于两头奶牛间有好感的描述,再给出 MDMD 条关于两头奶牛间存有反感的描述。你的工作是:如果不存在满足要求的方案,输出 −1−1;如果 11 号奶牛和 NN 号奶牛间的距离可以任意大,输出 −2−2;否则,计算出在满足所有要求的情况下,11 号奶牛和 NN 号奶牛间可能的最大距离。
思路:差分约束系统+spfa判负环,思维难道不高,但代码有一定难度。
做法:用边{a,b,c}表示b的位置-a的位置要
//By hpwwzyy2012
#include
using namespace std;
#define ll long long
const int N=1e3+1e2;
const int M=1e4+1e2;
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
bool f=0;char c=0;int x=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
struct node{
int next,to,w;
}e[(N+M)<<1];int h[N],tot;
//const int inf=0x3f3f3f3f;
inline void add(int a,int b,int c){
e[++tot]=(node){h[a],b,c};h[a]=tot;
}
ll d[N],n,cnt[N],inf;bool v[N];
inline bool spfa(int s){
memset(d,127,sizeof(d));
memset(cnt,0,sizeof(cnt));
memset(v,true,sizeof(v));
inf=d[0];d[s]=0;v[s]=false;
queue q;q.push(s);
do{
int z=q.front();q.pop();v[z]=true;
for(int i=h[z];i;i=e[i].next){
register int to=e[i].to;
if (d[to]>d[z]+e[i].w){
d[to]=d[z]+e[i].w;
cnt[to]=cnt[z]+1;
if (cnt[to]>=n) return false;
if (v[to]){
v[to]=false;
q.push(to);
}
}
}
}while (q.size());
return true;
}
int m,q,a,b,c,i;
int main(){
// freopen("t1.in","r",stdin);
n=read();m=read();q=read();
for(i=1;i