【2018年全国多校算法寒假训练营练习比赛(第四场)】ABCDEFGH
2018-02-11 19:18
746 查看
A石油采集
分析:二分匹配。一个油田只能够和一个油田匹配被瓢走 ,所以我们 对每一个油田 遍历其四周,如果也有油田,那么就建立边表示有可能匹配。 最后匈牙利算法求最大匹配就好了。
代码
#include<bits/stdc++.h> using namespace std; #define LL long long #define ULL unsigned long long const int N = 50*50+11; const int M = 1E6+11; const int mod = 1e9+7; const int inf = 0x3f3f3f3f; const LL inff = 0x3f3f3f3f3f3f3f3f; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch<='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } /*-------------------------*/ struct Edge { int from,to,next; }edge[M]; int head ,top; void init(){ memset(head,-1,sizeof(head)); top=0; } void addedge(int a,int b){ Edge e={a,b,head[a]}; edge[top]=e; head[a]=top++; } int used ,pipei ; bool Find(int x){ for(int i=head[x];i!=-1;i=edge[i].next){ Edge e=edge[i]; if(!used[e.to]){ used[e.to]=1; if(pipei[e.to]==-1 || Find(pipei[e.to])){ pipei[e.to]=x; return true; } } } return false; } int to[4][2]={0,1,0,-1,1,0,-1,0}; bool mp ; int solve(int n){ memset(pipei,-1,sizeof(pipei)); int ans=0; for(int i=1;i<=n*n;i++){ memset(used,0,sizeof(used)); if(Find(i) ) ans++; } return ans; } int main(){ int T;scanf("%d",&T);int zz=1; while(T--){ init(); memset(mp,0,sizeof(mp)); int n;scanf("%d",&n); for(int i=1;i<=n;i++){ string s;cin>>s; for(int j=0;j<n;j++){ if(s[j]=='#') mp[i][j+1]=true; else mp[i][j+1]=false; } } /* for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ printf("%d",mp[i][j]); } puts(""); }*/ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(!mp[i][j]) continue; for(int k=0;k<4;k++){ int nx=i+to[k][0]; int ny=j+to[k][1]; if(mp[nx][ny]) addedge((i-1)*n+j,(nx-1)*n+ny); // mp[nx][ny]=false ; } } } printf("Case %d: %d\n",zz++,solve(n)/2); // 重复 } return 0; } /* 2 6 ...... .##... ...... .#..#. .#..## ...... 4 ###. #... .### ..#. */
B道路建设
分析:最小生成树模板题代码
#include<bits/stdc++.h> using namespace std; #define LL long long #define ULL unsigned long long const int N = 1e5 +11; const int M = 1e6+11; const int inf = 0x3f3f3f3f; const LL inff= 0x3f3f3f3f3f3f3f3f ; const int mod = 1e9+7; const double PI = acos(-1.0); int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();} while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();} return x*f; } /*----------------------------------*/ struct Edge{ int from,to,val; }edge[M]; bool cmp(Edge a,Edge b){ return a.val<b.val; } int pre ; void init(int n){ for(int i=0;i<=n;i++) pre[i]=i; } int Find(int x){ return x==pre[x]?x:(pre[x]=Find(pre[x])); } void Join(int x,int y){ x=Find(x);y=Find(y); if(x!=y) pre[x]=y; } int main(){ int c,n,m; while(scanf("%d%d%d",&c,&n,&m)!=EOF){ init(m); for(int i=0;i<n;i++) scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].val); sort(edge,edge+n,cmp); int ans=0; int flag=1; for(int i=0;i<n;i++){ Edge e=edge[i]; if(Find(e.to)!=Find(e.from)){ Join(e.to,e.from); ans+=e.val; } } if(ans<=c) puts("Yes") ; else puts("No"); } return 0; } /* 链接:https://www.nowcoder.net/acm/contest/76/B 来源:牛客网 20 10 5 1 2 6 1 3 3 1 4 4 1 5 5 2 3 7 2 4 7 2 5 8 3 4 6 3 5 9 4 5 2 10 2 2 1 2 5 1 2 15 */
C求交集
分析:二分查找。我用map MLE了..QAQ
#include<bits/stdc++.h> using namespace std; #define LL long long #define ULL unsigned long long const int N = 2e6 +11; const int M = 1e6+11; const int inf = 0x3f3f3f3f; const LL inff= 0x3f3f3f3f3f3f3f3f ; const int mod = 1e9+7; const double PI = acos(-1.0); int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();} while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();} return x*f; } /*----------------------------------*/ int a ; int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF){ for(int i=0;i<n;i++) scanf("%d",&a[i]); int have=0; for(int i=0;i<m;i++){ int c;scanf("%d",&c); int pos=lower_bound(a,a+n,c)-a; if(a[pos]==c) { if(have++) putchar(' '); printf("%d",c); } } if(!have) puts("empty"); else puts(""); } return 0; }
D 小明的挖矿之旅
分析: 因为每个点只能够右和下移动,所以整个图就相当于一个DAG图。然后讨论入度为0 和出度为0的个数就行了#include<bits/stdc++.h> using namespace std; #define LL long long #define ULL unsigned long long const int N = 1000*1000 +11; const int M = 1000+11; const int inf = 0x3f3f3f3f; const LL inff= 0x3f3f3f3f3f3f3f3f ; const int mod = 1e9+7; const double PI = acos(-1.0); int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();} while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();} return x*f; } /*----------------------------------*/ //vector<int>ve ; int in ,out ; void init(int n){ for(int i=0;i<n;i++) { // ve[i].clear(); out[i]=in[i]=0; } } void addedge(int a,int b){ // ve[a].push_back(b); in[b]++; out[a]++; } bool mp[M][M]; void show(int n,int m){ for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ printf("%d",mp[i][j]); } puts(""); } } int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF){ init(n*m);memset(mp,0,sizeof(mp)); for(int i=0;i<n;i++){ string s;cin>>s; for(int j=0;j<m;j++){ if(s[j]=='.') mp[i+1][j+1]=true; else mp[i+1][j+1]=false; } } // show(n,m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(mp[i][j]){ int nx=i+1;int ny=j; if(mp[nx][ny]) addedge((i-1)*m+j-1,(nx-1)*m+ny-1); nx=i;ny=j+1; if(mp[nx][ny]) addedge((i-1)*m+j-1,(nx-1)*m+ny-1); } } } int a,b,c; a=b=c=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(mp[i][j]){ if(in[(i-1)*m+j-1]==0) a++; if(out[(i-1)*m+j-1]==0) b++; c++; } } } if(c==0) puts("0"); else if(a==c&&b==c) printf("%d\n",a-1); else printf("%d\n",max(a,b)); } return 0; }
E 通知小弟
分析:scc+缩点 ,求缩点后的入度 ,如果入度为0且HA能够通知到的间谍 不在这个缩点里的话,肯定是-1 ,否则就是入度为0的点的个数。只要入度为0的被通知了,那么入度不为的点肯定会由入度为0的传过来。
#include<bits/stdc++.h> using namespace std; #define LL long long #define ULL unsigned long long const int N = 1000 +11; const int M = 1e6+11; const int inf = 0x3f3f3f3f; const LL inff= 0x3f3f3f3f3f3f3f3f ; const int mod = 1e9+7; const double PI = acos(-1.0); int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();} while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();} return x*f; } /*----------------------------------*/ struct Edge{ int from,to,nexts; }edge[M]; int head ,top; int n,m; void init(){ memset(head,-1,sizeof(head)) ; top=0; } void addedge(int a,int b){ Edge e={a,b,head[a]} ; edge[top]=e;head[a]=top++; } int dfn ,low ; int sccno ,scc_cnt; stack<int>S; bool Instack ; vector<int>scc ; int mp ; int dfs_clock; void tarjan(int now){ low[now]=dfn[now]=++dfs_clock; S.push(now);Instack[now]=1; for(int i=head[now];i!=-1;i=edge[i].nexts){ Edge e=edge[i]; if(!dfn[e.to]){ tarjan(e.to); low[now]=min(low[now],low[e.to]); }else if(Instack[e.to]) low[now]=min(low[now],dfn[e.to]); } if(dfn[now]==low[now]){ scc_cnt++;scc[scc_cnt].clear(); for(;;){ int nexts=S.top();S.pop();Instack[nexts]=0; sccno[nexts]=scc_cnt; scc[scc_cnt].push_back(nexts); if(nexts==now) break; } } } void find_cut(int le,int ri){ memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(Instack,0,sizeof(Instack)); memset(sccno,0,sizeof(sccno)); dfs_clock=scc_cnt=0; for(int i=le;i<=ri;i++) if(!dfn[i]) tarjan(i); } int in ; void suodian(){ // 建立DAG图 for(int i=1;i<=scc_cnt;i++) memset(mp[i],0,sizeof(mp[i])); for(int i=1;i<=scc_cnt;i++) in[i]=0; for(int i=0;i<top;i++){ Edge e=edge[i]; int now=sccno[e.from]; int nexts=sccno[e.to]; if(now!=nexts){ in[nexts]++; mp[now][nexts]=1; } } } int HA ; map<int,int>zzx; int main(){ int mm; while(scanf("%d%d",&n,&mm)!=EOF){ init(); zzx.clear(); for(int i=1;i<=mm;i++) scanf("%d",&HA[i]); for(int i=1;i<=n;i++){ int num=0; scanf("%d",&num); for(int j=1;j<=num;j++){ int zz; scanf("%d",&zz); addedge(i,zz); } } find_cut(1,n); suodian(); //cout<<scc_cnt<<endl; for(int i=1;i<=mm;i++) zzx[sccno[HA[i]]]=1; int flag=1; int ans=0; for(int i=1;i<=scc_cnt;i++){ if(in[i]==0){ if(zzx[i]==0) flag=0; // HA通知到的间谍有没有这个在这里联通快中 ans++; } } if(!flag) puts("-1"); else printf("%d\n",ans); } return 0; }
F Call to your teacher
分析:floyd 求传递闭包 模板题代码
#include<bits/stdc++.h> using namespace std; #define LL long long #define ULL unsigned long long const int N = 100 +11; const int M = 1e6+11; const int inf = 0x3f3f3f3f; const LL inff= 0x3f3f3f3f3f3f3f3f ; const int mod = 1e9+7; const double PI = acos(-1.0); int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();} while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();} return x*f; } /*----------------------------------*/ int mp ; int n,m; void wall(){ for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++){ mp[i][j]=mp[i][j]|(mp[i][k]&mp[k][j]); } } } } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ memset(mp,0,sizeof(mp)); while(m--){ int a,b;scanf("%d%d",&a,&b); mp[a][b]=1; } wall(); if(mp[1] ) puts("Yes"); else puts("No"); } return 0; }
G 老子的意大利炮呢
分析: 状态压缩 + 优先队列的BFS不难,但是太菜了,没时间写了。
三种物品,可以用状态压缩来表示当前拥有的状态 。
1<<1 表示拥有第一件物品,1<<2表示拥有第二件物品 ,1<<3表示拥有第三件物品.
然后 就是针对每种情况逐个分析就行了 ,这里一定要思路清晰,不然很容易错。
代码
#include<bits/stdc++.h> using namespace std; #define LL long long #define ULL unsigned long long const int N = 100+11; const int M = 1E6+11; const int mod = 1e9+7; const int inf = 0x3f3f3f3f; const LL inff = 0x3f3f3f3f3f3f3f3f; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch<='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } /*-------------------------*/ struct Node { int x,y,step,state; bool operator<(const Node &b)const { return step>b.step; } }; int mp ,speed[1<<5]; int vis [1<<5]; int to[4][2]={1,0,0,1,-1,0,0,-1}; void Cal(int &cnt,int &tt,Node now){ cnt=0; tt=1; for(int i=1;i<=3;i++){ if((1<<i)&now.state){ cnt++; tt+=speed[1<<i]; } } } void bfs(Node st){ memset(vis,0,sizeof(vis)); priority_queue<Node>Q; Q.push(st); vis[st.x][st.y][st.state]=1; while(!Q.empty()){ Node now=Q.top(); Q.pop(); for(int i=0;i<4;i++){ int nx=now.x+to[i][1]; int ny=now.y+to[i][0]; if(mp[nx][ny]==0 || vis[nx][ny][now.state]) continue; //对所有的情况逐个分析 关键 if(mp[nx][ny]==6){ int cnt,tt; Cal(cnt,tt,now); if(cnt!=3){ Node next={nx,ny,now.step+tt,now.state}; vis[nx][ny][next.state]=1; Q.push(next); } continue; } if(mp[nx][ny]==5){ int cnt,tt; Cal(cnt,tt,now); if(cnt==3) { //printf("%d \n",tt); printf("%d\n",now.step+tt); return ; } continue; } if(mp[nx][ny]==1) { int cnt,tt; Cal(cnt,tt,now); Node ne={nx,ny,now.step+tt,now.state}; vis[nx][ny][ne.state]=1; Q.push(ne); continue; } if(mp[nx][ny]>=2&&mp[nx][ny]<=4){ int cnt,tt; Cal(cnt,tt,now); Node ne={nx,ny,now.step+tt,now.state | (1<<(mp[nx][ny]-1))}; vis[nx][ny][ne.state]=1; Q.push(ne); Node next={nx,ny,now.step+tt,now.state}; vis[nx][ny][next.state]=1; Q.push(next); continue; } } } puts("-1"); } void show(int n,int m){ //debug for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) { printf("%d",mp[i][j]); } puts(""); } } int main(){ memset(mp,0,sizeof(mp)); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ string s;cin>>s; for(int j=0;j<m;j++){ if(s[j]=='#') mp[i][j+1]=6; else mp[i][j+1]=1; } } Node st; for(int i=1;i<=5;i++){ int x,y;scanf("%d%d",&x,&y); if(i==1) { st.x=x;st.y=y;st.step=0;st.state=0; } mp[x][y]=i; } // show(n,m); speed[0]=1; for(int i=1;i<=3;i++){ int t;scanf("%d",&t); speed[1<<i]=t; } // for(int i=1;i<=3;i++) printf("%d ",speed[1<<i]); bfs(st); return 0; } /* 3 5 ##.## .#.#. ##.## 1 3 2 1 2 3 2 5 3 3 1 5 4 */
H 老子的全排列呢
分析:直接调用函数 。代码
#include<bits/stdc++.h> using namespace std; #define LL long long #define ULL unsigned long long const int N = 500 +11; const int M = 1e6+11; const int inf = 0x3f3f3f3f; const LL inff= 0x3f3f3f3f3f3f3f3f ; const int mod = 1e9+7; const double PI = acos(-1.0); int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();} while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();} return x*f; } /*----------------------------------*/ int a[8]={1,2,3,4,5,6,7,8}; int main(){ do{ for(int i=0;i<8;i++) printf("%d%s",a[i],i==7?"":" "); puts(""); }while(next_permutation(a,a+8)); return 0; }
相关文章推荐
- 2018年全国多校算法寒假训练营练习比赛(第四场)题解 F Call to your teacher(广深搜)
- 2018年全国多校算法寒假训练营练习比赛(第四场)F
- 2018年全国多校算法寒假训练营练习比赛(第四场)C
- (*)2018年全国多校算法寒假训练营练习比赛(第四场)D-小明的挖矿之旅(思路)
- 2018年全国多校算法寒假训练营练习比赛(第四场) - D - 小明的挖矿之旅
- 2018年全国多校算法寒假训练营练习比赛(第四场)解题报告
- 2018年全国多校算法寒假训练营练习比赛(第四场)题解
- 2018年全国多校算法寒假训练营练习比赛(第四场)-E-通知小弟(强连通缩点)
- 2018年全国多校算法寒假训练营练习比赛(第四场) - E - 通知小弟(BFS)
- 2018年全国多校算法寒假训练营练习比赛(第四场)G-老子的意大利炮呢
- 2018年全国多校算法寒假训练营练习比赛(第四场)B
- 2018年全国多校算法寒假训练营练习比赛(第四场) - G - 老子的意大利炮呢(搜索)
- 2018年全国多校算法寒假训练营练习比赛(第四场) A 石油采集 【二分匹配+DFS】
- nowcoder 2018年全国多校算法寒假训练营练习比赛(第四场)-老子的全排列呢
- 2018年全国多校算法寒假训练营练习比赛(第四场)【还在更新】
- 2018年全国多校算法寒假训练营练习比赛(第四场)H
- nowcoder 2018年全国多校算法寒假训练营练习比赛(第四场)-道路建设
- 2018年全国多校算法寒假训练营练习比赛(第四场)H-老子的全排列呢(dfs/STL)
- (*)2018年全国多校算法寒假训练营练习比赛(第四场)E-通知小弟(Kosaraju)
- Wannafly 2018年全国多校算法寒假训练营练习比赛(第四场) G 老子的意大利炮昵