1. 程式人生 > 其它 >省選模擬28

省選模擬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 題目名稱

不會