训练日记-多校
发布日期:2021-09-19 10:56:03 浏览次数:2 分类:技术文章

本文共 8117 字,大约阅读时间需要 27 分钟。

Delicious Apples

题目大概:

给出一个有n个位置的环,有m个位置有苹果树,你的仓库在0的位置,你有一个大小为k的篮子,问最少走多少步,可以把所有苹果拿到位置0的仓库。

思路:

有3中拿的方式

1,从右边走,拿够苹果,然后直接返回。

2,从左边走,拿够苹果,然后返回。

3,绕一圈,把所有剩余苹果拿走。

显然,第三种方式,是最后剩余的苹果很少<=k个时,这样拿一圈,可以会走的步数少。但也有可能直接回去少,需要比较。

利用背包,把这三种方式模拟一遍。

感想:

如果改在直线上,仓库位置不固定,会怎么样,那就没有绕圈拿了,直接分析前两种情况就i选哪个了,所有,很多题,有环后,就复杂了一些。

代码:

#include 
using namespace std;const int maxn=1e5+10;pair
G[maxn];long long d[maxn];long long dl[maxn],dr[maxn];int cmp(pair
a,pair
b){ return a.first
k) { dl[i]=dl[i-k]+d[i]; } else { dl[i]=d[i]; } } for(int i=cnt;i>=1;i--) { if(i+k<=cnt) { dr[i]=dr[i+k]+(2*L-d[i]); } else { dr[i]=(2*L-d[i]); } } long long ans=0; for(int i=0;i<=cnt;i++) { if(ans==0)ans=dl[i]+dr[i+1]; ans=min(ans,dl[i]+dr[i+1]); } for(int i=0;i+k+1<=cnt;i++) { ans=min(ans,dl[i]+dr[i+k+1]+L); } if(k>=cnt)ans=min(ans,L); printf("%I64d\n",ans); } return 0;}

Tricks Device

题目大概:

有一个迷宫,有n个房间,m条道。1为入口,n为出口。从1道n有最短路。

问最少切断几条道,可以使人不能从1走到n为最短路。

问最多切断几条道,还可以从1走最短路走到n。

思路:

求一遍1道n的最短路,并且维护1到n的最短路,最少变数为min,第二问答案就是m-min。

把图中的所有最短路的边重新建立最短路图,然后跑一边1到n的最大流。就是求的最小割。就是第一问的答案。

感想:

这是一个最短路和最大流结合的题目。

最大流,就考察了一个最小割转化为最大流来求,感觉难点还是求最短路的最少边,需要改变最短路的代码。

就是改动最短路的代码,既然可以求最少,也可以求最多,当然,也可以在最短路过程中维护其他的。

代码:

#include 
using namespace std;#define RPEF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define copy( a , x ) memcpy ( a , x , sizeof a )typedef long long LL ;const int MAXN = 3010 ;const int MAXE = 100010;const int MAXQ = 200010;const int INF = 0x3f3f3f3f;struct Edge { int v , n ; LL c ; Edge ( int var = 0 , LL cap = 0 , int next = 0 ) : v ( var ) , c ( cap ) , n ( next ) {}} ;struct netWork { Edge edge[MAXE] ; int adj[MAXN] , cntE ; int cur[MAXN] , d[MAXN] , num[MAXN] , pre[MAXN] ; bool vis[MAXN] ; int Q[MAXQ] , head , tail ; int s , t , nv ; LL flow ; void init () { cntE = 0 ; memset(adj,-1,sizeof(adj)); } void addedge ( int u , int v , LL c , LL rc = 0 ) { edge[cntE] = Edge ( v , c , adj[u] ) ; adj[u] = cntE ++ ; edge[cntE] = Edge ( u , rc , adj[v] ) ; adj[v] = cntE ++ ; } void rev_Bfs () { memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); d[t] = 0 ; vis[t] = 1 ; head = tail = 0 ; Q[tail ++] = t ; num[0] = 1 ; while ( head != tail ) { int u = Q[head ++] ; for ( int i = adj[u] ; ~i ; i = edge[i].n ) { int v = edge[i].v ; if ( vis[v] ) continue ; vis[v] = 1 ; d[v] = d[u] + 1 ; ++ num[d[v]] ; Q[tail ++] = v ; } } } LL ISAP () { copy ( cur , adj ) ; rev_Bfs () ; flow = 0 ; int i , u = pre[s] = s ; while ( d[s] < nv ) { if ( u == t ) { LL f = INF ; int pos ; for ( i = s ; i != t ; i = edge[cur[i]].v ) if ( f > edge[cur[i]].c ) f = edge[cur[i]].c , pos = i ; for ( i = s ; i != t ; i = edge[cur[i]].v ) edge[cur[i]].c -= f , edge[cur[i] ^ 1].c += f ; u = pos ; flow += f ; } for ( i = cur[u] ; ~i ; i = edge[i].n ) if ( edge[i].c && d[u] == d[edge[i].v] + 1 ) break ; if ( ~i ) { cur[u] = i ; pre[edge[i].v] = u ; u = edge[i].v ; } else { if ( 0 == ( -- num[d[u]] ) ) break ; int mmin = nv ; for ( i = adj[u] ; ~i ; i = edge[i].n ) if ( edge[i].c && mmin > d[edge[i].v] ) cur[u] = i , mmin = d[edge[i].v] ; d[u] = mmin + 1 ; ++ num[d[u]] ; u = pre[u] ; } } return flow ; }} ;netWork net ;int n,m;struct node1{ int v,next,w;}edge[MAXE];int id;int head[MAXN];void init1(){ memset(head,-1,sizeof(head)); id=0;}void addedge(int u,int v,int w){ edge[id].v=v; edge[id].w=w; edge[id].next=head[u]; head[u]=id++; edge[id].v=u; edge[id].w=w; edge[id].next=head[v]; head[v]=id++;}bool vis[MAXN];int side[MAXN];int dist[MAXN];void spfa(int s){ memset(vis,false,sizeof(vis)); memset(dist,INF,sizeof(dist)); memset(side,INF,sizeof(side)); vis[s]=true; dist[s]=0; side[s]=0; queue
que; while(!que.empty()) que.pop(); que.push(s); while(!que.empty()) { int u=que.front(); que.pop(); vis[u]=false; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if (dist[v]>dist[u]+edge[i].w) { dist[v]=dist[u]+edge[i].w; side[v]=side[u]+1; if (!vis[v]) { vis[v]=true; que.push(v); } } if (dist[v]==dist[u]+edge[i].w) { side[v]=min(side[u]+1,side[v]); if (!vis[v]) { vis[v]=true; que.push(v); } } } }}void getmap(){ for(int i=1;i<=n;i++) { for(int j=head[i];j!=-1;j=edge[j].next) { int v=edge[j].v; if(dist[v]==dist[i]+edge[j].w) net.addedge(i,v,1); } }}int main(){ while(scanf("%d%d",&n,&m)!=EOF) { int u,v,w; init1(); for(int i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } spfa(1); net.init(); getmap(); net.s=1;net.t=n;net.nv=net.t+1; printf("%I64d %d\n",net.ISAP(),m-side[n]); } return 0;}

 

Annoying problem

题目大概:

给出一棵树,n个点,(n-1)条边,然后给出q个操作,有一个集合s。每次操作后,给出s集合中所有点相连的最短路长度。

1  x   为s集合增加x节点,

2  x  把s集合中的x节点删除。

思路:

用dfs序和lca就可以解决这道题。

dis数组是给点到根的长度,lca(x,y)求x和ylca。

用了一个公式,dis【u】-dis【lca(x,u)】-dis【lca(y,u)】+dis【lca(x,y)】;

有点容斥的味道。

感想:

dfs序有很多树上的应用,算是一种简单树链剖分题的有效解决方法。

代码:

#include 
using namespace std;const int maxn=1e5+50;int cnt;int head[maxn<<1];struct poin{ int to,w,next;}edge[maxn<<1];set
s;int dis[maxn],dxu[maxn],be[maxn],d[maxn];int vis[maxn];int fa[maxn][25];void add(int u,int v,int w){ edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].to=u; edge[cnt].w=w; edge[cnt].next=head[v]; head[v]=cnt++;}int ans;void init(){ cnt=0; ans=0; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); memset(dxu,0,sizeof(dxu)); memset(fa,0,sizeof(fa)); s.clear();}void dfs(int u,int fat){ dxu[u]=++ans; be[ans]=u; for(int i=1; i<19; i++) { fa[u][i]=fa[fa[u][i-1]][i-1]; } for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; int w=edge[i].w; if(v==fat)continue; d[v]=d[u]+1; dis[v]=dis[u]+w; fa[v][0]=u; dfs(v,u); }}int lca(int x,int y){ if(d[x]
=0; i--) { if(d[fa[x][i]]>=d[y]) x=fa[x][i]; if(x==y)return x; } for(int i=19; i>=0; i--) { if(fa[x][i]!=fa[y][i]) { x=fa[x][i]; y=fa[y][i]; } } return fa[x][0];}int solve(int u){ if( s.empty() ) return 0 ; int x , y ; set
::iterator iter; iter = s.upper_bound(u) ; if( iter == s.end() || iter == s.begin() ) { x = be[ *s.begin() ] ; y = be[ *s.rbegin()] ; } else { x = be[*iter] ; iter-- ; y = be[*iter] ; } u = be[u] ; /* cout<<"****"<

 

转载地址:https://blog.csdn.net/a1046765624/article/details/81106392 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:训练日记
下一篇:训练日记-多校

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月02日 14时57分05秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章