省选模拟28
这两天不知道咋了,精神抖擞,考试没有睡觉......
第一题,有点意思,一步一步往外推,先推到拓扑序,意识到需要缩点,然后发现要用网络流,可以说是搞了好久
第二题,一眼看上去没有思路,果断放弃
第三题,仍然没有思路
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 题目名称
不会
QQ:2953174821