省選模擬28
阿新 • • 發佈:2022-03-08
這兩天不知道咋了,精神抖擻,考試沒有睡覺......
第一題,有點意思,一步一步往外推,先推到拓撲序,意識到需要縮點,然後發現要用網路流,可以說是搞了好久
第二題,一眼看上去沒有思路,果斷放棄
第三題,仍然沒有思路
T1 我
不說了,縮點+網路流
AC_code
#include<bits/stdc++.h> using namespace std; #define fo(i,x,y) for(int i=(x);i<=(y);i++) #define fu(i,x,y) for(int i=(x);i>=(y);i--) int read(){ int s=0,t=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();} while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} return s*t; } const int N=65; const int inf=0x3f3f3f3f; int T,n,m,ys[N*2],cys,buc[N],ans; char ch[N],s[4005][5]; struct E{int to,nxt;}e[4005]; int head[N],rp; void add_edg(int x,int y){ e[++rp].to=y;e[rp].nxt=head[x];head[x]=rp; } int dfn[N],low[N],cnt,cd[N]; bool vi[N]; int bl[N],hav[N],siz[N],cbl,sta[N],top; void tarjan(int x){ dfn[x]=low[x]=++cnt;sta[++top]=x; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].to; if(!dfn[y])tarjan(y),low[x]=min(low[x],low[y]); else if(!bl[y])low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]){ bl[x]=++cbl;siz[cbl]++; if(!buc[x])hav[cbl]++; while(sta[top]!=x){ bl[sta[top]]=cbl; if(!buc[sta[top]])hav[cbl]++; top--;siz[cbl]++; }top--; } } struct NET{ int s=126,t=127; struct E{int to,nxt,val;}e[4205*10]; int head[N*2],hea[N*2],rp; void add_edg(int x,int y,int z){ e[++rp].to=y;e[rp].nxt=head[x]; e[rp].val=z;head[x]=rp; } void clear(){memset(head,0,sizeof(head));rp=1;} int dis[N*2]; bool bfs(){ memcpy(head,hea,sizeof(hea)); memset(dis,0x3f,sizeof(dis)); queue<int> q;while(!q.empty())q.pop(); q.push(s);dis[s]=0; while(!q.empty()){ int x=q.front();q.pop(); // cerr<<x<<endl; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].to; // cerr<<x<<" "<<y<<" "<<e[i].val<<" "<<dis[y]<<endl; if(!e[i].val||dis[y]<=dis[x]+1)continue; dis[y]=dis[x]+1;q.push(y); if(y==t)return true; } } return false; } int dfs(int x,int in){ if(x==t)return in; int go=0,rest=in; // cerr<<x<<" "<<in<<endl; for(int i=head[x];i;head[x]=i=e[i].nxt){ int y=e[i].to; if(!e[i].val||dis[y]!=dis[x]+1)continue; go=dfs(y,min(e[i].val,rest)); if(go)rest-=go,e[i].val-=go,e[i^1].val+=go; else dis[y]=0; if(!rest)break; } return in-rest; } int dinic(){ int ret=0; memcpy(hea,head,sizeof(hea)); while(bfs())ret+=dfs(s,inf); return ret; } }net; signed main(){ freopen("graph.in","r",stdin); freopen("graph.out","w",stdout); // cerr<<(int)'Z'<<" "<<(int)'z'<<" "<<(int)'9'<<endl; T=read(); fo(i,'0','9')ys[i]=++cys; fo(i,'a','z')ys[i]=++cys; fo(i,'A','Z')ys[i]=++cys; while(T--){ // cerr<<ys['a']<<endl; memset(buc,0,sizeof(buc)); memset(bl,0,sizeof(bl)); memset(hav,0,sizeof(hav)); memset(siz,0,sizeof(siz)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(cd,0,sizeof(cd)); memset(vi,false,sizeof(vi)); memset(head,0,sizeof(head)); rp=cbl=cnt=ans=top=0;net.clear(); scanf("%s",ch+1);m=read(); n=strlen(ch+1); fo(i,1,n)buc[ys[ch[i]]]++; fo(i,1,m){ scanf("%s",s[i]+1); add_edg(ys[s[i][1]],ys[s[i][2]]); } fo(i,1,cys){if(!bl[i])tarjan(i);if(buc[i])ans++;} // cerr<<ans<<endl; fo(i,1,m)cd[bl[ys[s[i][1]]]]++; fo(i,1,cbl){ if(!hav[i]&&(cd[i]||siz[i]>1)){ ans--;hav[i]++;vi[i]=true; net.add_edg(net.s,i,1); net.add_edg(i,net.s,0); } net.add_edg(i+cbl,net.t,hav[i]); net.add_edg(net.t,i+cbl,0); } // cerr<<ans<<endl; fo(i,1,m){ if(bl[ys[s[i][1]]]!=bl[ys[s[i][2]]]){ net.add_edg(bl[ys[s[i][1]]],bl[ys[s[i][2]]]+cbl,inf); net.add_edg(bl[ys[s[i][2]]]+cbl,bl[ys[s[i][1]]],0); // net.add_edg(bl[ys[s[i][1]]]+cbl,bl[ys[s[i][2]]],inf); // net.add_edg(bl[ys[s[i][2]]],bl[ys[s[i][1]]]+cbl,0); net.add_edg(bl[ys[s[i][1]]]+cbl,bl[ys[s[i][2]]]+cbl,inf); net.add_edg(bl[ys[s[i][2]]]+cbl,bl[ys[s[i][1]]]+cbl,0); } } printf("%d\n",ans+net.dinic()); } return 0; }
T2 想不出
尤拉定理,然後找最大的交點數就行了,直接根據左右兩側的點個數定向!!
AC_code
#include<bits/stdc++.h> using namespace std; #define fo(i,x,y) for(int i=(x);i<=(y);i++) #define fu(i,x,y) for(int i=(x);i>=(y);i--) int read(){ int s=0,t=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();} while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} return s*t; } const int N=2005; const double eps=1e-15; struct VEC{ double x,y; VEC(){}VEC(double a,double b){x=a;y=b;} VEC operator + (VEC a)const{return VEC(x+a.x,y+a.y);} VEC operator - (VEC a)const{return VEC(x-a.x,y-a.y);} VEC operator * (double a)const{return VEC(x*a,y*a);} VEC operator / (double a)const{return VEC(x/a,y/a);} double operator * (VEC a)const{return x*a.x+y*a.y;} double operator ^ (VEC a)const{return x*a.y-y*a.x;} }dot[N],ll[N],rr[N],zx,yx; int n,ans,cl,cr; bool judle(VEC x,VEC y){ VEC dw=VEC(-1.0,-sqrt(3.0)),up=VEC(-1.0,sqrt(3.0)); return ((dw^(x-y))<=0&&(up^(x-y))>=0); } bool judri(VEC x,VEC y){ VEC dw=VEC(1.0,-sqrt(3.0)),up=VEC(1.0,sqrt(3.0)); return ((dw^(x-y))>=0&&(up^(x-y))<=0); } bool coml(VEC a,VEC b){ return a.x==b.x?a.y<b.y:a.x<b.x; } signed main(){ freopen("surface.in","r",stdin); freopen("surface.out","w",stdout); n=read();int u=(1<<n)-1; fo(i,1,n)scanf("%lf%lf",&dot[i].x,&dot[i].y); zx=VEC(-1.0,-sqrt(3.0)); yx=VEC(1.0,-sqrt(3.0)); fo(i,1,n){ int le=0,ri=0; fo(j,1,n){ if(i==j)continue; if(judle(dot[j],dot[i]))le++; if(judri(dot[j],dot[i]))ri++; } if(le>=ri)ll[++cl]=dot[i]; else rr[++cr]=dot[i]; } sort(ll+1,ll+cl+1,coml); fo(i,1,cl){ fo(j,1,cr){ if((zx^(rr[j]-ll[i]))>0)continue; if((yx^(ll[i]-rr[j]))<0)continue; ans++; } } ans=ans+1-n; printf("%d",ans); return 0; }
T3 題目名稱
不會