照例先放个链接$QwQ$

$A$

$QwQ$之前写过题解辣.

重新说下趴,就给横坐标纵坐标也开点,然后每个点连向对应横纵坐标边权为$0$,相邻横坐标点之间连边,相邻纵坐标点之间连边,跑个最短路就完事$QwQ$

还有一种想法是先按$x$排序相邻相连,再按$y$排序相邻相连.因为两个不相邻的一定能通过两个相邻达到,所以是对的.

$upd:$

我是真的自闭,,,之前做这题的时候$bzoj$在维护,我就在$darkbzoj$上交,过了.

然后今天在$bzoj$上交,不是$TLE$就是$MLE$,就很自闭.

调了很久之后发现是数组开大了:)

$wzbl$

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define lf double
#define gc getchar()
#define mp make_pair
#define int long long
#define P pair<int,int>
#define t(i) edge[i].to
#define w(i) edge[i].wei
#define ri register int
#define rc register char
#define rb register bool
#define lowbit(x) (x&(-x))
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)
#define e(i,x) for(ri i=head[x];i;i=edge[i].nxt)
#define lbh(x) lower_bound(sth+1,sth+1+h_cnt,x)-sth
#define lbl(x) lower_bound(stl+1,stl+1+l_cnt,x)-stl const int N=5e5+10;
int n,h_cnt,sth[N],l_cnt,stl[N],ed_cnt,head[N<<1],S,T,dis[N<<1],vis[N<<1];
struct node{int x,y;}nod[N];
struct ed{int to,nxt,wei;}edge[N<<3];
priority_queue< P,vector<P>,greater<P> >Q; il int read()
{
rc ch=gc;ri x=0;rb y=1;
while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
if(ch=='-')ch=gc,y=0;
while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
return y?x:-x;
}
il void ad(ri x,ri y,ri z){/*printf("%d %d %d\n",x,y,z);*/edge[++ed_cnt]=(ed){x,head[y],z};head[y]=ed_cnt;}
il void dij()
{
memset(dis,63,sizeof(dis));dis[S]=0;Q.push(mp(0,S));
while(!Q.empty())
{
ri nw=Q.top().second;Q.pop();if(vis[nw])continue;vis[nw]=1;
//printf("nw=%d dis=%d\n",nw,dis[nw]);
e(i,nw)if(dis[t(i)]>dis[nw]+w(i))dis[t(i)]=dis[nw]+w(i),Q.push(mp(dis[t(i)],t(i)));
}
} signed main()
{
//freopen("4152.in","r",stdin);freopen("4152.out","w",stdout);
n=read();rp(i,1,n)nod[i]=(node){sth[++h_cnt]=read(),stl[++l_cnt]=read()};
sort(sth+1,sth+1+h_cnt);h_cnt=unique(sth+1,sth+h_cnt+1)-sth-1;rp(i,1,n)nod[i].x=lbh(nod[i].x);
sort(stl+1,stl+1+l_cnt);l_cnt=unique(stl+1,stl+l_cnt+1)-stl-1;rp(i,1,n)nod[i].y=lbl(nod[i].y);
rp(i,2,h_cnt)ad(i,i-1,sth[i]-sth[i-1]),ad(i-1,i,sth[i]-sth[i-1]);
rp(i,2,l_cnt)ad(i+h_cnt,i-1+h_cnt,stl[i]-stl[i-1]),ad(i-1+h_cnt,i+h_cnt,stl[i]-stl[i-1]);
rp(i,1,n){ri t1=i+h_cnt+l_cnt,t2=nod[i].y+h_cnt;ad(t1,nod[i].x,0),ad(nod[i].x,t1,0),ad(t1,t2,0),ad(t2,t1,0);}
S=1+h_cnt+l_cnt;T=n+h_cnt+l_cnt;dij();printf("%lld\n",dis[T]);
return 0;
}

$B$

题目大意可以上洛谷康康.注意下是有向边就成$/kel$

考虑到一个强联通分量内肯定全部可以拿走,所以跑个$tarjan$缩点,就成了一个$DAG$.

然后随便$dp$一下就完事,$QwQ$

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define t(i) edge[i].to
#define w(i) edge[i].wei
#define rp(i,x,y) for(int i=x;i<=y;++i)
#define e(i,x) for(int i=head[x];i;i=edge[i].nxt) const int N=1e6+10;
int n,m,S,bl[N],bl_cnt,fr[N],to[N],wei[N],dat[N]; namespace pre
{
int head[N],ed_cnt,dfn[N],low[N],dfn_cnt,stck[N],top;
bool instck[N];
struct ed{int to,nxt,wei;}edge[N];
void ad(int x,int y,int z){edge[++ed_cnt]=(ed){x,head[y],z};head[y]=ed_cnt;}
void tarjan(int nw)
{
dfn[nw]=low[nw]=++dfn_cnt;stck[++top]=nw;instck[nw]=1;
e(i,nw)
{
if(!dfn[t(i)])tarjan(t(i)),low[nw]=min(low[nw],low[t(i)]);
else if(instck[t(i)])low[nw]=min(low[nw],dfn[t(i)]);
}
if(dfn[nw]==low[nw])
{
++bl_cnt;
while(stck[top]^nw){bl[stck[top]]=bl_cnt;instck[stck[top--]]=0;}bl[nw]=bl_cnt,instck[nw]=0,--top;
}
}
void main()
{scanf("%lld%lld",&n,&m);rp(i,1,m){scanf("%lld%lld%lld",&fr[i],&to[i],&wei[i]);ad(to[i],fr[i],wei[i]);}scanf("%lld",&S);rp(i,1,n)if(!dfn[i])tarjan(i);}
}
namespace work
{
int head[N],ed_cnt,f[N],as,qwq[N],sum[N],qwq_cnt;
struct ed{int to,nxt,wei;}edge[N];
queue<int>Q;
int cal(int w){int t=sqrt(2*w+0.25)-0.5;return w*(t+1)-(t+1)*(t+2)*t/6;}
void ad(int x,int y,int z){edge[++ed_cnt]=(ed){x,head[y],z};head[y]=ed_cnt;}
int dp(int nw){if(f[nw])return f[nw];e(i,nw)f[nw]=max(f[nw],dp(t(i))+w(i));return f[nw]+=dat[nw];}
void main(){rp(i,1,m)if(bl[fr[i]]^bl[to[i]])ad(bl[to[i]],bl[fr[i]],wei[i]);else dat[bl[fr[i]]]+=cal(wei[i]);printf("%lld\n",dp(bl[S]));}
} signed main(){pre::main();work::main();return 0;}

$C$

考虑对$a$中每个位置$i$,记录一个它之后的最近的序列$p$中对应的最近的下一个位置.

然后发现对每个位置,往后跳$n-1$次就能跑完一个排列嘛.

所以对每个位置求一个$ans_i$表示它跑完一个排列最早在哪儿结束,这个倍增随便搞下就出来了.

然后每次询问就查询$[l,r]$里的$ans_{min}$和$r$的大小关系,$st$表维护一波就完事$QwQ$

一个小$trick$是如果你是记录的$ans_i$表示向前跑最晚在哪儿结束就可以不用考虑初始化的问题了$/kel$

(虽然我写的向后跑$/kel$

注意区分下$n$和$m$,,,我因为这个$WA$了两三次$/dk$

#include<bits/stdc++.h>
using namespace std;
#define my(i,x,y) for(int i=x;i>=y;--i)
#define rp(i,x,y) for(int i=x;i<=y;++i) const int N=2e5+10;
int n,m,q,p[N],rk[N],a[N],nxt[N][22],st[N][22],lg[N];
vector<int>V[N]; int query(int l,int r){int len=r-l+1;return min(st[l][lg[len]],st[r-(1<<lg[len])+1][lg[len]]);} int main()
{
scanf("%d%d%d",&n,&m,&q);memset(nxt,63,sizeof(nxt));memset(st,63,sizeof(st));rp(i,1,m)st[i][0]=i;lg[0]=-1;rp(i,1,m)lg[i]=lg[i>>1]+1;
rp(i,1,n)scanf("%d",&p[i]),rk[p[i]]=i;;p[0]=p[n];
rp(i,1,m)
{
scanf("%d",&a[i]);int dat=p[rk[a[i]]-1];
while(V[dat].size()){int nw=V[dat].size()-1;nxt[V[dat][nw]][0]=i;V[dat].pop_back();}V[a[i]].push_back(i);
}
rp(i,1,19)rp(j,1,m)if(nxt[j][i-1]<=m)nxt[j][i]=nxt[nxt[j][i-1]][i-1];
int t=n-1;my(i,19,0)if(t>=(1<<i)){rp(j,1,m)if(st[j][0]<=m)st[j][0]=nxt[st[j][0]][i];t-=(1<<i);}
rp(i,1,19)rp(j,1,m-(1<<i)+1)st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
while(q--){int l,r,pos;scanf("%d%d",&l,&r);pos=query(l,r);printf(pos<=r?"1":"0");}
return 0;
}

$D$

蛮经典的题,在$PPT$上都看到两次辣$QwQ$.

嗷然后因为我第一次看题的时候理解错题意了所以先港下,就这里是线段不是直线鸭$QwQ$

首先说下.因为上方下方其实是差不多做的所以我就只说上方了$QwQ$

考虑枚举哪个颜色不选,然后找到一个极大边界数点就成.

发现直接枚举不太好做,于是把所有点按$y$排序,从高到低加入,每次加入就等价于枚举了颜色和下边界.

左右边界可以在加入的时候顺便按$x$排序加入$set$中,每次查询当前加入点的前驱后继就知道左右边界了.

然后树状数组数点就成.

嗷注意还有一种情况,就是存在对$y$没有限制即两个$x$相邻的点同色.这个在$set$里查下就成$QwQ$

因为多组数据所以注意清零$QwQ$

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&(-x))
#define my(i,x,y) for(int i=x;i>=y;--i)
#define rp(i,x,y) for(int i=x;i<=y;++i)
#define lb(x) lower_bound(st+1,st+st_cnt+1,x)-st const int N=200000+10;
int n,m,st[N],st_cnt,tr[N],as;
struct node{int col,x,y;}nod[N];
vector<int>V[N];
set<int>S[N];
set<int>::iterator it; void ad(int x){while(x<=st_cnt)++tr[x],x+=lowbit(x);}
int query(int nw){int ret=0;while(nw)ret+=tr[nw],nw-=lowbit(nw);return ret;} int main()
{
//freopen("4548.in","r",stdin);freopen("4548.out","w",stdout);
int T;scanf("%d",&T);
while(T--)
{
as=0;st_cnt=0;scanf("%d%d",&n,&m);rp(i,1,n){int x,y,z;scanf("%d%d%d",&x,&y,&z);st[++st_cnt]=x,st[++st_cnt]=y;nod[i]=(node){z,x,y};}
sort(st+1,st+1+st_cnt);st_cnt=unique(st+1,st+1+st_cnt)-st-1;rp(i,1,n)nod[i].x=lb(nod[i].x),V[nod[i].y=lb(nod[i].y)].push_back(i);
memset(tr,0,sizeof(tr));rp(i,1,m)S[i].clear(),S[i].insert(0),S[i].insert(st_cnt+1);
rp(i,1,st_cnt)
{
int sz=V[i].size();
rp(k,0,sz-1)
{
int l,r,j=V[i][k];
it=S[nod[j].col].upper_bound(nod[j].x);--it;l=*it;it=S[nod[j].col].lower_bound(nod[j].x);r=*it;as=max(as,query(r-1)-query(l));
}
rp(k,0,sz-1){int j=V[i][k];S[nod[j].col].insert(nod[j].x),ad(nod[j].x);}
}
rp(i,1,m){it=S[i].begin();while((*it)^(st_cnt+1)){int l=*it;++it;as=max(as,query((*it)-1)-query(l));}}
memset(tr,0,sizeof(tr));rp(i,1,m)S[i].clear(),S[i].insert(0),S[i].insert(st_cnt+1);
my(i,st_cnt,1)
{
int sz=V[i].size();
rp(k,0,sz-1)
{
int l,r,j=V[i][k];
it=S[nod[j].col].upper_bound(nod[j].x);--it;l=*it;it=S[nod[j].col].lower_bound(nod[j].x);r=*it;as=max(as,query(r-1)-query(l));
}
rp(k,0,sz-1){int j=V[i][k];S[nod[j].col].insert(nod[j].x),ad(nod[j].x);}
V[i].clear();
}
rp(i,1,m){it=S[i].begin();while((*it)^(st_cnt+1)){int l=*it;++it;as=max(as,query((*it)-1)-query(l));}}
printf("%d\n",as);
}
return 0;
}

$E$

,,,我感觉这题我见过七八遍了.

不想说了$QAQ$

#include<algorithm>
#include<iomanip>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define il inline
#define gc getchar()
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,l,r) for(ri i=l;i<=r;++i)
#define my(i,l,r) for(ri i=l;i>=r;--i) const int N=210;
int n,color[N],cnt[N],f[N][N][N],now,ct,ans; il int read()
{
rc ch=gc;ri x=0;rb y=1;
while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
if(ch=='-')ch=gc,y=0;
while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
return y?x:-x;
}
int bfs(int l,int r,int k)
{
if(f[l][r][k]!=0)return f[l][r][k];if(l>r)return 0;
f[l][r][k]=bfs(l,r-1,0)+(cnt[r]+k)*(cnt[r]+k);
rp(i,l,r-1)if(color[i]==color[r])f[l][r][k]=max(bfs(l,i,cnt[r]+k)+bfs(i+1,r-1,0),f[l][r][k]);
return f[l][r][k];
} int main()
{
// freopen("QAQ.in","r",stdin);freopen("QAQ.out","w",stdout);
ri T=read();
rp(i,1,T)
{
memset(color,0,sizeof(color));memset(f,0,sizeof(f));now=1;n=read();
rp(j,1,n){ct=read();if(ct==color[now])++cnt[now];else{++now;cnt[now]=1;color[now]=ct;}}
ans=bfs(1,now,0);
cout<<"Case "<<i<<": "<<ans<<endl;
}
return 0;
}

$F$

$QwQ$很久很久之前就做过辣.

#include<bits/stdc++.h>
using namespace std;
long long f[100015]={1};
long long read()
{
char ch=getchar();
long long x=0,y=1;
while((ch!='-') && (ch>'9' || ch<'0'))ch=getchar();
if(ch=='-')y=-1,ch=getchar();
while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
return x*y;
}
int main()
{
long long c[5];c[1]=read(),c[2]=read(),c[3]=read(),c[4]=read();long long tot=read();
for(long long i=1;i<=4;++i)
for(long long j=c[i];j<=100001;++j)f[j]+=f[j-c[i]];
while(tot>0)
{
tot--;
long long d1=read(),d2=read(),d3=read(),d4=read(),s=read(),ans=f[s];
if((d1+1)*c[1]<=s)ans-=f[s-((d1+1)*c[1])];
if((d2+1)*c[2]<=s)ans-=f[s-((d2+1)*c[2])];
if((d3+1)*c[3]<=s)ans-=f[s-((d3+1)*c[3])];
if((d4+1)*c[4]<=s)ans-=f[s-((d4+1)*c[4])];
if((d1+1)*c[1]+(d2+1)*c[2]<=s)ans+=f[s-((d1+1)*c[1])-(d2+1)*c[2]];
if((d1+1)*c[1]+(d3+1)*c[3]<=s)ans+=f[s-((d1+1)*c[1])-(d3+1)*c[3]];
if((d1+1)*c[1]+(d4+1)*c[4]<=s)ans+=f[s-((d1+1)*c[1])-(d4+1)*c[4]];
if((d2+1)*c[2]+(d3+1)*c[3]<=s)ans+=f[s-((d2+1)*c[2])-(d3+1)*c[3]];
if((d2+1)*c[2]+(d4+1)*c[4]<=s)ans+=f[s-((d2+1)*c[2])-(d4+1)*c[4]];
if((d3+1)*c[3]+(d4+1)*c[4]<=s)ans+=f[s-((d3+1)*c[3])-(d4+1)*c[4]];
if((d1+1)*c[1]+(d2+1)*c[2]+(d3+1)*c[3]<=s)ans-=f[s-((d1+1)*c[1])-(d2+1)*c[2]-(d3+1)*c[3]];
if((d1+1)*c[1]+(d2+1)*c[2]+(d4+1)*c[4]<=s)ans-=f[s-((d1+1)*c[1])-(d2+1)*c[2]-(d4+1)*c[4]];
if((d1+1)*c[1]+(d4+1)*c[4]+(d3+1)*c[3]<=s)ans-=f[s-((d1+1)*c[1])-(d4+1)*c[4]-(d3+1)*c[3]];
if((d4+1)*c[4]+(d2+1)*c[2]+(d3+1)*c[3]<=s)ans-=f[s-((d4+1)*c[4])-(d2+1)*c[2]-(d3+1)*c[3]];
if((d1+1)*c[1]+(d2+1)*c[2]+(d3+1)*c[3]+(d4+1)*c[4]<=s)ans+=f[s-((d1+1)*c[1])-(d2+1)*c[2]-(d3+1)*c[3]-(d4+1)*c[4]];
cout<<ans<<endl;
}
return 0;
}

$G$

没有脑子,不会贪心,说个最暴力的做法趴$QwQ$

考虑类似蔬菜的套路,先按$t_1$排序,然后每栋楼尽量放结尾.

然后珂朵莉树维护下哪些时间能放就完事.$QwQ$

$over$

#include<bits/stdc++.h>
using namespace std;
#define P pair<int,int>
#define mp make_pair
#define rp(i,x,y) for(int i=x;i<=y;++i) const int N=150000+10;
int n,as;
P nod[N];
set<P>S; void split(int x)
{
set<P>::iterator it=S.upper_bound(mp(x+1,0));if(it==S.begin())return;--it;if((*it).second<=x)return;
P tmp=*it;S.erase(it);S.insert(mp(tmp.first,x));if(tmp.second>x)S.insert(mp(x+1,tmp.second));
}
int check(int tim,int ddl)
{
split(ddl);set<P>::iterator it=S.upper_bound(mp(ddl+1,0)),tmp=it;int nw=0;
while(tmp!=S.begin()){--tmp;nw+=(*tmp).second-(*tmp).first+1;if(nw>=tim)break;}
if(nw<tim)return 0;;int t=(*tmp).first+(nw-tim);split(t-1);tmp=S.lower_bound(mp(t,0));while(tmp!=it)S.erase(tmp++);return 1;
} int main()
{
scanf("%d",&n);rp(i,1,n)scanf("%d%d",&nod[i].first,&nod[i].second);sort(nod+1,nod+1+n);
S.insert(mp(1,INT_MAX));rp(i,1,n)as+=check(nod[i].first,nod[i].second);printf("%d\n",as);
return 0;
}

$H$

不难想到肯定优先用数量多的之间配对?

用堆维护下数量就完事.$QwQ$

$QwQQQQQ$注意一个细节,就一定是每次取出来之后只拿一个,不能把第三大的全拿完了$QwQ$

#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define P pair<int,int>
#define rp(i,x,y) for(int i=x;i<=y;++i)
#define lb(x) lower_bound(st+1,st+1+st_cnt,x)-st const int N=1e5+10;
int n,r[N],st[N],st_cnt,num[N],as,as1[N],as2[N],as3[N];
priority_queue<P>Q; void print(int x,int y,int z){if(x<y)swap(x,y);if(x<z)swap(x,z);if(y<z)swap(y,z);printf("%d %d %d\n",x,y,z);} int main()
{
scanf("%d",&n);rp(i,1,n)scanf("%d",&r[i]),st[i]=r[i];sort(st+1,st+1+n);st_cnt=unique(st+1,st+1+n)-st-1;rp(i,1,n)++num[lb(r[i])];
rp(i,1,st_cnt)Q.push(mp(num[i],st[i]));
while(Q.size()>2)
{
P t1,t2,t3;t1=Q.top();Q.pop();t2=Q.top();Q.pop();t3=Q.top();Q.pop();
as1[++as]=t1.second,as2[as]=t2.second,as3[as]=t3.second;
--t1.first,--t2.first,--t3.first;if(t1.first)Q.push(t1);if(t2.first)Q.push(t2);if(t3.first)Q.push(t3);
}
printf("%d\n",as);rp(i,1,as)print(as1[i],as2[i],as3[i]);
return 0;
}

$I$

$QwQ$首先一个性质,就这个操作的顺序是无影响的,所以可以强制从小到大决策,最后乘以全排列就完事.

然后考虑剪枝.

注意到它这里分段的时候每段其实是固定的了.

所以在决策第$i$个决策的时候,可以考虑将序列分成$2^{i-1}$段,然后如果每段内部的顺序都是连续且递增的就不要操作.如果有一段内部不满足就把这一段内部的搞下,如果有两段内部不满足就把它们之间搞下,如果有超过两段不满足就直接$GG$了.

核心思想在于由局部推到整体.即因为是从小到大搞的,所以在决策第$i$个的时候,显然$2^{i-2}$长度的序列是有序的了,就只用考虑$2^{i-1}$的序列了$QwQ$.

$over$

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rp(i,x,y) for(int i=x;i<=y;++i) const int N=1e6+;
int n,m,a[N],fac[],as; bool chck(int len){for(int i=;i<=m;i+=(len<<))if((a[i]+len)^(a[i+len]))return ;return ;}
void swp(int x,int y,int l){rp(i,,l-)swap(a[x+i],a[y+i]);}
void dfs(int len,int cnt)
{
if(len^ && !chck(len>>))return;;if(!(len^m)){as+=fac[cnt];return;}
dfs(len<<,cnt);int p[],gdgs=;
for(int i=;i<=m;i+=(len<<))if((a[i]+len)^a[i+len]){if(!(gdgs^))return;else p[++gdgs]=i,p[++gdgs]=i+len;}
rp(i,,gdgs)rp(j,i+,gdgs)swp(p[i],p[j],len),dfs(len<<,cnt+),swp(p[i],p[j],len);
} signed main(){scanf("%lld",&n);m=<<n;rp(i,,m)scanf("%lld",&a[i]);fac[]=;rp(i,,n)fac[i]=fac[i-]*i;dfs(,);printf("%lld\n",as);return ;}

$J$

听$lyh$说要$A*$?我头铁写了发搜索过了$QwQ$

#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define P pair<int,int>
#define rp(i,x,y) for(int i=x;i<=y;++i)
#define lb(x) lower_bound(st+1,st+1+st_cnt,x)-st const int N=50+5,inf=1e9;
int n,m,ed_cnt,as_cnt,as,lk[N][N],sq_cnt,sz[N],rlsz[N],num[N]; int nam_h(int x,int y){return (n<<1|1)*(x-1)+y;}
int nam_l(int x,int y){return (n<<1|1)*(x-1)+y+n;}
void pre()
{
scanf("%d%d",&n,&m);ed_cnt=2*n*(n+1);as=n*n;sq_cnt=0;
rp(i,1,ed_cnt)num[i]=1;rp(i,1,m){int x;scanf("%d",&x);num[x]=0;}
memset(lk,0,sizeof(lk));sq_cnt=0;
rp(i,1,n)
rp(j,1,n-i+1)
rp(k,1,n-i+1)
{
sz[++sq_cnt]=0;rlsz[sq_cnt]=4*i;
rp(p,0,i-1)
{
int t1=nam_h(j,k+p),t2=nam_h(j+i,k+p),t3=nam_l(j+p,k),t4=nam_l(j+p,k+i);//printf(" t1=%d t2=%d t3=%d t4=%d num=%d %d %d %d\n",t1,t2,t3,t4,num[t1],num[t2],num[t3],num[t4]);
lk[sq_cnt][t1]=lk[sq_cnt][t2]=lk[sq_cnt][t3]=lk[sq_cnt][t4]=1;sz[sq_cnt]+=num[t1]+num[t2]+num[t3]+num[t4];
}
//printf("sz[%d]=%d rlsz[%d]=%d\n",sq_cnt,sz[sq_cnt],sq_cnt,rlsz[sq_cnt]);
} }
int fd(){rp(i,1,sq_cnt)if(!(rlsz[i]^sz[i]))return i;return -1;}
void dfs(int stp)
{
if(stp>=as)return;;int nw=fd();if(!(~nw)){as=stp;return;}
rp(i,1,ed_cnt)if(lk[nw][i]){rp(j,1,sq_cnt)if(lk[j][i])--sz[j];dfs(stp+1);rp(j,1,sq_cnt)if(lk[j][i])++sz[j];}
} int main()
{
// freopen("1603.in","r",stdin);freopen("1603.out","w",stdout);
int T;scanf("%d",&T);
while(T--){pre();dfs(0);printf("%d\n",as);}
return 0;
}

$K$

题目大意说给定一个图,每条边有边权,有$K$条边可以把边权变为$0$.问$S$到$T$的路径上最大边权的最小值是多少.

$umm$这个不是一看就二分嘛?考虑二分这个权值$mid$.然后长度大于$mid$的边权设为$1$,小于等于$mid$的设为$0$.跑个最短路就完事.

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define t(i) edge[i].to
#define w(i) edge[i].wei
#define rp(i,x,y) for(int i=x;i<=y;++i)
#define e(i,x) for(int i=head[x];i;i=edge[i].nxt) const int N=1000+10,M=10000+10;
int n,m,K,head[N],ed_cnt,dis[N],l=1e9,r;
bool vis[N];
struct ed{int to,nxt,wei;}edge[M<<1];
struct ED{int fr,to,wei;}EDGE[M];
deque<int>Q; void ad(int x,int y,int z){edge[++ed_cnt]=(ed){x,head[y],z};head[y]=ed_cnt;edge[++ed_cnt]=(ed){y,head[x],z};head[x]=ed_cnt;}
int bfs()
{
memset(dis,63,sizeof(dis));dis[1]=0;Q.push_front(1);
while(!Q.empty())
{
int nw=Q.front();Q.pop_front();if(vis[nw])continue;
e(i,nw)if(dis[t(i)]>dis[nw]+w(i)){dis[t(i)]=dis[nw]+w(i);dis[nw]^dis[t(i)]?Q.push_back(t(i)):Q.push_front(t(i));}
}
return dis[n];
}
bool check(int dat)
{
ed_cnt=0;memset(head,0,sizeof(head));memset(vis,0,sizeof(vis));
rp(i,1,m)ad(EDGE[i].fr,EDGE[i].to,(bool)(EDGE[i].wei>dat));
return bfs()<=K;
} int main()
{
//freopen("3662.in","r",stdin);
scanf("%d%d%d",&n,&m,&K);rp(i,1,m)scanf("%d%d%d",&EDGE[i].fr,&EDGE[i].to,&EDGE[i].wei),l=min(l,EDGE[i].wei),r=max(r,EDGE[i].wei);
while(l<r){int mid=(l+r)>>1;if(check(mid))r=mid;else l=mid+1;}printf("%d\n",l);
return 0;
}

最新文章

  1. Torch7学习笔记(四)StochasticGradient
  2. Codeforces Round #149 (Div. 2)
  3. morris.js 简单学习
  4. ubuntu14.04.2 添加ppa remastersys源 镜像ubuntu系统
  5. vmware workstation11虚拟机破解版(附安装教程) 32/64位
  6. linux服务器安全小知识
  7. VPN连接在遇到飞鱼星设备时可能出现的疑难问题
  8. H264相关随笔
  9. Python dir()函数
  10. js与php传递参数
  11. OGG数据仓库以及单向复制(一)
  12. 封装一个button上带图片的,图片在上,文字在下的按钮
  13. MS SQL 事务日志管理小结
  14. centos7安装、配置、卸载jdk1.8
  15. opencart3图片Google Merchant Center验证通过不了的解决方法
  16. 终端(命令行)连接MySQL
  17. Ubuntu18.04中配置QT5.11开发环境
  18. frameset的用法
  19. 提示ORA-01144: File size (13107200 blocks) exceeds maximum of 4194303 blocks 最大4194303 block(转)
  20. temp-2017-4-20

热门文章

  1. laravel中如何实现验证码验证及使用
  2. Vue.js 第2章 钩子函数&amp;自定义指令&amp;过滤器&amp;计算属性&amp;侦听器
  3. @bzoj - 3749@ [POI2015] Łasuchy
  4. UISearchDisplayController “No Results“ cancel修改
  5. NodeMCU快速上云集锦
  6. javascript 宽度和高度
  7. TabHost选项卡的实现(二):使用Fragment实现
  8. Python--day63--图书管理系统表结构设计
  9. 【js】Vue 2.5.1 源码学习 (八)响应式入口observe
  10. P1085 管家的忠诚