上一场自己状态爆表;这一场队友爆表,自己捡表了;题目呢,总的来说不难,相比于前面几场比赛来说,关键在于如何建图。
像D题,在我的上一个博客里面就是一道同理的题,只需要求入度为0和出度为0的点最大数,然后特判已经强连通(比如只有一个点)的情况。
【A 石油采集】
题解:二分匹配之匈牙利。
【B 道路建设】
题解:并查集。
【C 求交集】
题解:双指针扫一遍即可。
【D 小明的挖矿之旅】
题解:求度为0的点数量。
【E 通知小弟】
题解:处理入度为0的新点;
【F Call to your teacher】
题解:
【G 老子的意大利炮呢】
题解:分层+优先队列SPFA。
【H 老子的全排列呢】
题解:STL之permutation或者试一试康拓展开。
【A】 12月份刚好看过队友做过此题,有印象。附上队友博客:LZH
#include<iostream> #include<cstdio> #include<cstring> #include<ctime> #include<cstdlib> #include<algorithm> #include<cmath> #include<string> using namespace std; int read(){ int xx=0,ff=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)ff=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){xx=(xx<<3)+(xx<<1)+ch-‘0‘;ch=getchar();} return xx*ff; } const int ws_[4]={0,1,0,-1},ad_[4]={1,0,-1,0}; int N,cas=0; char mp[55][55]; inline int id(int x,int y) {return (x-1)*N+y;} int lin[3100],len; struct edge{ int y,next; }e[100010]; inline void insert(int xx,int yy){ e[++len].next=lin[xx]; lin[xx]=len; e[len].y=yy; } inline void ins(int xx,int yy) {insert(xx,yy),insert(yy,xx);} bool vis[3100]; int match[3100]; bool hun(int x){ for(int i=lin[x];i;i=e[i].next) if(!vis[e[i].y]){ vis[e[i].y]=1; if(match[e[i].y]==0||hun(match[e[i].y])){ match[e[i].y]=x; match[x]=e[i].y; return 1; } } return 0; } int main(){ //freopen("in","r",stdin); for(int T=read();T;T--){ printf("Case %d: ",++cas); char ch; N=read(); for(int i=1;i<=N;i++) for(int j=1;j<=N;j++){ ch=getchar(); while(ch==‘ ‘||ch==‘\n‘) ch=getchar(); mp[i][j]=ch; } memset(lin,0,sizeof(lin));len=0; for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) if(mp[i][j]==‘#‘) for(int k=0;k<=3;k++){ int tx=i+ws_[k],ty=j+ad_[k]; if(tx<=0||ty<=0||tx>N||ty>N) continue; if(mp[tx][ty]==‘#‘) ins(id(i,j),id(tx,ty)); } memset(match,0,sizeof(match)); int ans=0; for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) if(mp[i][j]==‘#‘){ if(!match[id(i,j)]){ memset(vis,0,sizeof(vis)); if(hun(id(i,j))) ans++; } } printf("%d\n",ans); } }
【B】 并查集
#include<iostream> #include<cstdio> #include<cstring> #include<ctime> #include<cstdlib> #include<algorithm> #include<cmath> #include<string> using namespace std; int read(){ int xx=0,ff=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)ff=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){xx=(xx<<3)+(xx<<1)+ch-‘0‘;ch=getchar();} return xx*ff; } int C,N,M; struct edge{ int x,y,v; bool friend operator<(const edge&A,const edge&B) {return A.v<B.v;} }e[10010]; int father[110]; int getfather(int x){ if(father[x]==x) return x; return father[x]=getfather(father[x]); } int main(){ //freopen("in","r",stdin); while(scanf("%d",&C)!=EOF){ N=read(),M=read(); for(int i=1;i<=N;i++) e[i].x=read(),e[i].y=read(),e[i].v=read(); sort(e+1,e+1+N); for(int i=1;i<=M;i++) father[i]=i; int cnt=0; long long ans=0; for(int i=1;i<=N;i++){ int f1=getfather(e[i].x),f2=getfather(e[i].y); if(f1==f2) continue; cnt++; ans+=e[i].v; father[f2]=f1; if(cnt==M-1) break; } if(ans<=C) printf("Yes\n"); else printf("No\n"); } return 0; }
【C】 双指针
#include<iostream> #include<cstdio> #include<cstring> #include<ctime> #include<cstdlib> #include<algorithm> #include<cmath> #include<string> using namespace std; int read(){ int xx=0,ff=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)ff=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){xx=(xx<<3)+(xx<<1)+ch-‘0‘;ch=getchar();} return xx*ff; } const int maxn=1000010; int a[maxn],b[maxn],N,M; int ans[maxn],tp; int main(){ while(scanf("%d %d",&N,&M)!=EOF){ for(int i=1;i<=N;i++) a[i]=read(); for(int i=1;i<=M;i++) b[i]=read(); int i=1,j=1,tp=0; while(i<=N&&j<=M){ if(a[i]==b[j]) ans[++tp]=a[i],i++,j++; else if(a[i]>b[j]) j++; else i++; } if(tp==0) printf("empty\n"); else { for(int k=1;k<tp;k++) printf("%d ",ans[k]); printf("%d\n",ans[tp]); } } return 0; }
【D】