zoukankan      html  css  js  c++  java
  • 算法竞赛入门经典 写题笔记(第五章 图论算法与模型3)

    本节内容——

    • 生成树相关问题
    • 二分图最大匹配
    • 二分图最佳完美匹配
    • 稳定婚姻问题

    知识点部分

    例题20 秦始皇修路

    秦朝有n(n<=1000)个城市,需要修建一些道路使得任意两个城市之间都可以联通。道士徐福生成他可以用法术修路,不花钱,也不用劳动力,但只能修一条路,因此需要慎重选择法术修建哪一条路。秦始皇不仅希望其他道路的总长度B尽量短(这样可以节省劳动力),还希望法术连接的两个城市的人口之和A尽量大,因此下令寻找一个A/B最大的方案。

    我们可以先建立出最小生成树,然后枚举每条边(u,v),然后删除最小生成树上(u,v)之间的路径上的最大权(maxcost[u][v])

    现在的问题就是如何O(n)的求出来在最小生成树上到一个点的路径上的最大值。而这个也不难,一个dfs就完事了。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define MAXN 2010
    using namespace std;
    int n,m,t,T,cnt;
    int head[MAXN],fa[MAXN];
    double maxx[MAXN][MAXN];
    struct Edge{int nxt,to;double dis;}edge[MAXN*MAXN];
    struct Node{int x,y,w;}node[MAXN];
    struct Line{int u,v;double dis;}line[MAXN*MAXN];
    inline void add(int from,int to,double dis)
        {edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;}
    inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline bool cmp(Line x,Line y){return x.dis<y.dis;}
    inline double dist(int a,int b)
        {return sqrt((node[a].x-node[b].x)*(node[a].x-node[b].x)+(node[a].y-node[b].y)*(node[a].y-node[b].y));}
    inline void init(int now,int x,int pre,double cur_ans)
    {
        maxx[now][x]=cur_ans;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==pre) continue;
            init(now,v,x,max(cur_ans,edge[i].dis));
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&T);
        while(T--)
        {
            memset(head,0,sizeof(head));
            t=cnt=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++) fa[i]=i;
            for(int i=1;i<=n;i++)
                scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].w);
            for(int i=1;i<=n;i++)
                for(int j=i+1;j<=n;j++)
                    line[++cnt]=(Line){i,j,dist(i,j)};
            sort(&line[1],&line[cnt+1],cmp);
            // for(int i=1;i<=cnt;i++) printf("dis[%d]=%.2lf
    ",i,line[i].dis); 
            // cout<<endl;
            int sum=0;
            double all=0.0;
            for(int i=1;i<=cnt;i++)
            {
                int a=find(line[i].u),b=find(line[i].v);
                // printf("u=%d v=%d a=%d b=%d
    ",line[i].u,line[i].v,a,b);
                if(a==b) continue;
                fa[a]=b;
                sum++;
                all+=line[i].dis;
                add(line[i].u,line[i].v,line[i].dis),add(line[i].v,line[i].u,line[i].dis);
                if(sum==n-1) break;
            }
            // printf("all=%.2lf
    ",all);
            for(int i=1;i<=n;i++) init(i,i,-1,0);
            // for(int i=1;i<=n;i++)
            //     for(int j=i+1;j<=n;j++)
            //         printf("maxx[%d][%d]=%2.lf
    ",i,j,maxx[i][j]);
            double ans=0.0;
            for(int i=1;i<=n;i++)
                for(int j=i+1;j<=n;j++)
                    ans=max(ans,1.0*(node[i].w+node[j].w)/(all-maxx[i][j]));
            printf("%.2lf
    ",ans);
        }
        return 0;
    }
    

    例题21 邦德

    有n座城市通过m条双向道路相连,每条道路都有一个危险系数。你的任务是回答若干个询问,每个询问包含一个起点s和一个终点t,要求找到一条从s到t的路,使得途径所有边的最大危险系数最小。

    求最小瓶颈路。我们还可以按照上面那个题的思想,在dfs的时候更新到一个点的最值。
    但是这样子是(O(n^2))的。
    看到数据范围想到(log)的时间复杂度——数据结构?好像不星啊。那就倍增吧......
    挺好写的

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define MAXN 100010
    using namespace std;
    int n,m,t,q,kase;
    int head[MAXN],fa[MAXN][20],maxx[MAXN][20],dep[MAXN],ff[MAXN];
    struct Edge{int nxt,to,dis;}edge[MAXN<<1];
    struct Line{int u,v,w;}line[MAXN<<1];
    inline int find(int x){return x==ff[x]?x:ff[x]=find(ff[x]);}
    inline bool cmp(struct Line x,struct Line y){return x.w<y.w;}
    inline void add(int from,int to,int dis)
    {
        edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;
        edge[++t].nxt=head[to],edge[t].to=from,edge[t].dis=dis,head[to]=t;
    }
    inline void dfs(int x,int pre)
    {
        dep[x]=dep[pre]+1;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==pre) continue;
            maxx[v][0]=edge[i].dis;
            fa[v][0]=x;
            dfs(v,x);
        }
    }
    inline void init()
    {
        for(int j=1;j<=19;j++)
        {
            for(int i=1;i<=n;i++)
            {
                fa[i][j]=fa[fa[i][j-1]][j-1];
                // printf("maxx[%d][%d]=max(%d %d)
    ",i,j,maxx[i][j-1],maxx[fa[i][j-1]][j-1]);
                maxx[i][j]=max(maxx[i][j-1],maxx[fa[i][j-1]][j-1]);
            }
        }
        // for(int i=1;i<=n;i++)
        //     for(int j=0;j<=2;j++)
        //         printf("fa[%d][%d]=%d maxx[%d][%d]=%d
    ",i,j,fa[i][j],i,j,maxx[i][j]);
    }
    inline int query(int x,int y)
    {
        // printf("x=%d y=%d
    ",x,y);
        int cur_ans=0;
        if(dep[x]<dep[y]) swap(x,y);
        int cur=dep[x]-dep[y];
        for(int i=19;i>=0;i--)
            if(cur&(1<<i))
            {
                cur_ans=max(cur_ans,maxx[x][i]),x=fa[x][i];
                // printf("cur_ans=%d x=%d
    ",cur_ans,x);
            }
        if(x==y) return cur_ans;
        for(int i=19;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])
            {
                cur_ans=max(cur_ans,maxx[x][i]);
                cur_ans=max(cur_ans,maxx[y][i]);
                x=fa[x][i],y=fa[y][i];
            }
        }
        cur_ans=max(cur_ans,maxx[x][0]);
        cur_ans=max(cur_ans,maxx[y][0]);
        return cur_ans;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        while(scanf("%d%d",&n,&m)==2)
        {
            if(kase==0) kase++;
            else puts("");
            memset(head,0,sizeof(head));
            memset(fa,0,sizeof(fa));
            memset(maxx,0,sizeof(maxx));
            memset(dep,0,sizeof(dep));
            t=0;
            for(int i=1;i<=n;i++) ff[i]=i;
            for(int i=1;i<=m;i++)
                scanf("%d%d%d",&line[i].u,&line[i].v,&line[i].w);
            sort(&line[1],&line[m+1],cmp);
            int sum=0;
            for(int i=1;i<=m;i++)
            {
                int a=find(line[i].u),b=find(line[i].v);
                if(a!=b)
                {
                    ff[a]=b;
                    sum++;
                    add(line[i].u,line[i].v,line[i].w);
                    if(sum==n-1) break;
                }
            }
            // for(int i=1;i<=n;i++)
            // {
            //     cout<<"i="<<i<<" ";
            //     for(int j=head[i];j;j=edge[j].nxt)
            //         cout<<edge[j].to<<" ";
            //     cout<<endl;
            // }
            dfs(1,0);
            init();
            scanf("%d",&q);
            while(q--)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                printf("%d
    ",query(x,y));
            }
        }
        return 0;
    }
    

    例题22 比赛网络

    你需要花费步超过cost元来搭建一个比赛网络。网络中有n台机器,编号为0~n-1,其中机器0为服务器,其他机器为客户机。一共有m条可以使用的网线,其中第i条网线的发送端是机器(u_i),接受端是机器(v_i)(数据只能从机器(u_i)单向传输到机器(v_i)),带宽为(b_i Kbps),费用为(c_i)元。每台客户机应当恰好从一台机器接受数据(即恰好有一条网线的接受端是该机器),而服务器不应从任何机器接受数据。你的任务是最大化网络中的最小带宽。

    嘛.....就是二分带宽+最小有向生成树(最小树形图)判断.......
    不会最小树形图的可以去我的学习笔记里面看OI树上问题 简单学习笔记QAQ

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 100010
    #define INF 0x3f3f3f3f
    using namespace std;
    int cost,T,ans;
    int top[MAXN],id[MAXN],minn[MAXN],fa[MAXN];
    struct Edge{int u,v,dis,id,c;}edge[MAXN<<1],pre[MAXN<<1];
    inline bool solve(int n,int m,int root)
    {
        ans=0;
        while(233)
        {
            int cnt=0;
            for(int i=1;i<=n;i++) id[i]=top[i]=fa[i]=0,minn[i]=INF;
            for(int i=1;i<=m;i++)
            {
                int u=edge[i].u,v=edge[i].v;
                if(u!=v&&edge[i].dis<minn[v])
                    fa[v]=u,minn[v]=edge[i].dis; 
            }
            minn[root]=0;
            for(int i=1;i<=n;i++)
            {
                if(minn[i]==INF) return false;
                ans+=minn[i];
                int u;
                for(u=i;u!=root&&top[u]!=i&&!id[u];u=fa[u]) top[u]=i;
                if(u!=root&&!id[u])
                {
                    id[u]=++cnt;
                    for(int v=fa[u];v!=u;v=fa[v]) id[v]=cnt;
                }
            }
            if(!cnt) return true;
            for(int i=1;i<=n;i++) 
                if(!id[i])
                    id[i]=++cnt;
            for(int i=1;i<=m;i++)
            {
                int u=edge[i].u,v=edge[i].v;
                int last=minn[v];
                if((edge[i].u=id[u])!=(edge[i].v=id[v]))
                    edge[i].dis-=last;
            }
            n=cnt,root=id[root];
        }
    }
    inline bool check(int n,int m,int x)
    {
        int kkk=0;
        ans=0;
        for(int i=1;i<=m;i++)
            if(pre[i].c>=x) edge[++kkk]=pre[i];
        // printf("x=%d
    ",x);
        // for(int i=1;i<=kkk;i++)
        //     printf("%d %d %d %d
    ",edge[i].u,edge[i].v,edge[i].c,edge[i].dis);
        if(solve(n,kkk,1)==false) return false;
        // printf("ans=%d
    ",ans);
        if(ans<=cost) return true;
        else return false;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&T);
        int m,n;
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&cost);
            // printf("n=%d m=%d cost=%d
    ",n,m,cost);
            int l=INF,r=0,ansans=-1;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%d%d",&pre[i].u,&pre[i].v,&pre[i].c,&pre[i].dis);
                // printf("%d d %d %d
    ",pre[i].u,pre[i].v,pre[i].c,pre[i].dis);
                pre[i].u++,pre[i].v++;
                l=min(l,pre[i].c);
                r=max(r,pre[i].c);
            }
            // printf("l=%d r=%d
    ",l,r);
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(check(n,m,mid)) ansans=mid,l=mid+1;
                else r=mid-1;
            }
            if(ansans==-1) printf("streaming not possible.
    ");
            else printf("%d kbps
    ",ansans);
        }
        return 0;
    }
    

    例题23 蚂蚁

    给出n个白点和n个黑点的坐标,要求用n条不相交的线段把它们连接起来,其中每条线段恰好连接一个白点和一个黑点,每个点恰好连接到一条线段。
    对于二维平面上的点,如果要用不相交的线连起来,最后线段总长度最小的方案(即二分图最佳完美匹配)就是解
    题面pdf上的样例输出给错了。
    我用的dinic跑的。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define MAXN 310
    #define INF 1e9
    #define S 0
    #define T 2*n+1
    using namespace std;
    int n,m,t=1,c;
    int head[MAXN],cur[MAXN],done[MAXN],pre_e[MAXN],pre_v[MAXN];
    double f;
    double dis[MAXN];
    struct Edge{int nxt,to,dis;double cost;}edge[MAXN*MAXN*2];
    struct Node{int x,y;}node[MAXN];
    inline double dist(int a,int b){
        return sqrt(1.0*(node[a].x-node[b].x)*(node[a].x-node[b].x)+1.0*(node[a].y-node[b].y)*(node[a].y-node[b].y));
    }
    inline void add(int from,int to,int dis,double cost)
    {
        edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,edge[t].cost=cost,head[from]=t;
        edge[++t].nxt=head[to],edge[t].to=from,edge[t].dis=0,edge[t].cost=-cost,head[to]=t;
    }
    inline bool spfa()
    {
        queue<int>q; 
        for(int i=0;i<=T;i++) dis[i]=1e9;
        memset(done,0,sizeof(done));
        q.push(S);dis[S]=0;done[S]=1;
        while(!q.empty())
        {
            int u=q.front();q.pop();done[u]=0;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(edge[i].dis>0.0&&dis[u]+edge[i].cost<dis[v])
                {
                    dis[v]=dis[u]+edge[i].cost;
                    pre_e[v]=i,pre_v[v]=u;
                    if(!done[v])
                        q.push(v),done[v]=1;
                }
            }
        }
        if(dis[T]>=1e9) return false;
        int flow=0x3f3f3f3f;
        for(int i=T;i!=S;i=pre_v[i]) flow=min(flow,edge[pre_e[i]].dis);
        for(int i=T;i!=S;i=pre_v[i]) edge[pre_e[i]].dis-=flow,edge[pre_e[i]^1].dis+=flow;
        f+=flow;
        c+=flow*dis[T];
        return true;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        while(scanf("%d",&n)==1)
        {
            memset(head,0,sizeof(head));
            t=1;
            for(int i=1;i<=n;i++) scanf("%d%d",&node[i].x,&node[i].y);
            for(int i=1;i<=n;i++) scanf("%d%d",&node[i+n].x,&node[i+n].y);
            for(int i=1;i<=n;i++) add(S,i,1,0);//printf("[%d %d] 1 0
    ",S,i);
            for(int i=1;i<=n;i++) add(i+n,T,1,0);//printf("[%d %d] 1 0
    ",i+n,T);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    add(i,j+n,1,dist(i,j+n));//printf("[%d %d] 1 %.2lf
    ",i,j+n,dist(i,j+n));
            while(spfa());
            // printf("c=%d f=%.2lf
    ",c,f);
            for(int i=1;i<=n;i++)
            {
                for(int j=head[i];j;j=edge[j].nxt)
                {
                    if(edge[j].dis==0&&edge[j].to!=S)
                    {
                        printf("%d
    ",edge[j].to-n);
                        break;
                    }
                }
            }
        }
        return 0;
    }
    

    例题24 少林决胜

    给定一个N*N的矩阵,每个格子里都有一个正整数(w(i,j))。你的任务是给定每行确定一个整数(row(i)),每列也确定一个整数(col(i)),使得对于任意格子((i,j))(w(i,j)le row(i)+col(j))。所有row(i)和col(i)之和应当尽量小。

    “还记得KM算法里面的(l(x)+l(y)>=w(x,y))吗?算法结束结束后,所有顶标和是最小的。”
    ......
    于是跑一遍KM就行了QAQ

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define MAXN 510
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,kase,ans;
    int w[MAXN][MAXN],lx[MAXN],ly[MAXN],to[MAXN];
    bool S[MAXN],T[MAXN];
    inline int match(int x)
    {
        S[x]=true;
        for(int j=1;j<=n;j++)
            if(lx[x]+ly[j]==w[x][j]&&!T[j])
            {
                T[j]=true;
                if(!to[j]||match(to[j]))
                {
                    to[j]=x;
                    return true;
                }
            }
        return false;
    }
    inline void update()
    {
        int d=INF;
        for(int i=1;i<=n;i++)
            if(S[i])
                for(int j=1;j<=n;j++)
                    if(!T[j])
                        d=min(d,lx[i]+ly[j]-w[i][j]);
        for(int i=1;i<=n;i++)
        {
            if(S[i]) lx[i]-=d;
            if(T[i]) ly[i]+=d;
        }
    }
    inline void KM()
    {
        for(int i=1;i<=n;i++)
        {
            lx[i]=ly[i]=to[i]=0;
            for(int j=1;j<=n;j++) lx[i]=max(lx[i],w[i][j]);
        }
        for(int i=1;i<=n;i++)
        {
            while(233)
            {
                for(int j=1;j<=n;j++) S[j]=T[j]=0;
                if(match(i)) break;
                else update();
            }
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        while(scanf("%d",&n)!=EOF)
        {
            ans=0;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    scanf("%d",&w[i][j]);
            KM();
            for(int i=1;i<n;i++) printf("%d ",lx[i]),ans+=lx[i];
            printf("%d
    ",lx[n]),ans+=lx[n];
            for(int i=1;i<n;i++) printf("%d ",ly[i]),ans+=ly[i];
            printf("%d
    ",ly[n]),ans+=ly[n];
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    例题25 固定分区内存管理

    感觉和这个题差不多。
    不过还要输出调度方案......具体请看代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<queue>
    #define MAXN 60
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,m,nm,kase;
    int start[MAXN],belong[MAXN];
    int runtime[MAXN][MAXN],w[MAXN*10][MAXN*10];
    int head[MAXN],siz[MAXN],s[MAXN],t[MAXN],number[MAXN];
    int l[MAXN*10],lx[MAXN*10],ly[MAXN*10];
    bool S[MAXN*10],T[MAXN*10];
    vector<int>G[MAXN*10];
    inline void add(int from,int to,int dis)
    {
        // printf("[%d %d] %d
    ",from,to,dis);
        G[from].push_back(to);
        w[from][to]=dis;
    }
    inline bool match(int x)
    {
        S[x]=true;
        for(int i=0;i<G[x].size();i++)
        {
            int v=G[x][i];
            if(lx[x]+ly[v]==w[x][v]&&!T[v])
            {
                T[v]=true;
                if(!l[v]||match(l[v]))
                {
                    l[v]=x;
                    return true;
                }
            }
        }
        return false;
    }
    inline void update()
    {
        int d=INF;
        for(int i=1;i<=nm;i++)
            if(S[i])
                for(int cur=0;cur<G[i].size();cur++)
                {
                    int j=G[i][cur];
                    if(!T[j])
                        d=min(d,lx[i]+ly[j]-w[i][j]);
                }
        for(int i=1;i<=nm;i++)
        {
            if(S[i]) lx[i]-=d;
            if(T[i]) ly[i]+=d;
        }
    }
    inline void solve()
    {
        for(int i=1;i<=nm;i++)
        {
            lx[i]=ly[i]=l[i]=0;
            for(int j=1;j<=nm;j++)
                if(w[i][j]>lx[i])
                    lx[i]=w[i][j];
        }
        for(int i=1;i<=nm;i++)
        {
            while(233)
            {
                for(int j=1;j<=nm;j++) S[j]=T[j]=0;
                if(match(i)) break;
                else update();
            }
        }
    }
    inline void print()
    {
        int all_time=0;
        for(int i=1;i<=m;i++)
        {
            vector<int>programs;
            for(int j=1;j<=n;j++)
            {
                int r=n*(i-1)+j;
                int cur=l[r];
                if(cur>n) break;
                programs.push_back(cur);
                belong[cur]=i;
                all_time-=w[cur][r]; 
            }
            reverse(programs.begin(),programs.end());
            int cur_time=0;
            for(int j=0;j<programs.size();j++)
            {
                start[programs[j]]=cur_time;
                cur_time+=runtime[programs[j]][i];
            }
        }
        printf("Case %d
    ",++kase);
        printf("Average turnaround time = %.2lf
    ",(double)all_time/n);
        for (int i=1;i<=n;i++) 
            printf("Program %d runs in region %d from %d to %d
    ",i,belong[i],start[i],start[i]+runtime[i][belong[i]]);
        printf("
    ");
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        while(scanf("%d%d",&m,&n)==2)
        {
            if(n==0&&m==0) break;
            nm=n*m;
            for(int i=1;i<=nm;i++) G[i].clear();
            memset(w,0,sizeof(w));
            for(int i=1;i<=m;i++) scanf("%d",&siz[i]);
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&number[i]);
                for(int j=1;j<=number[i];j++) scanf("%d%d",&s[j],&t[j]);
                for(int j=1;j<=m;j++)
                {
                    runtime[i][j]=-1;
                    if(siz[j]<s[1]) continue;
                    for(int k=1;k<=number[i];k++)
                    {
                        if(siz[j]<s[k+1]||k==number[i])
                        {runtime[i][j]=t[k];break;}
                    }
                }
            }
            // for(int i=1;i<=n;i++)
            //     for(int j=1;j<=m;j++)
            //         printf("runtime[%d][%d]=%d
    ",i,j,runtime[i][j]);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    if(runtime[i][j]!=-1)
                        for(int k=1;k<=n;k++)
                            add(i,(j-1)*n+k,-runtime[i][j]*k);
            for(int i=n+1;i<=nm;i++)
                for(int j=1;j<=nm;j++)
                    add(i,j,1);
            solve();
            print();
        }
        return 0;
    } 
    

    例题26 女士的选择

    稳定婚姻模板题

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define MAXN 1010
    using namespace std;
    int T,n,kase;
    int to_girl[MAXN],to_boy[MAXN];
    int a[MAXN][MAXN],order[MAXN][MAXN],nxt[MAXN];
    queue<int>q;
    inline void solve(int x,int y)
    {
        int cur=to_boy[y];
        if(cur)
        {
            to_girl[cur]=0;
            q.push(cur);
        }
        to_girl[x]=y,to_boy[y]=x;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&T);
        while(T--)
        {
            while(!q.empty()) q.pop();
            memset(to_girl,0,sizeof(to_girl));
            memset(to_boy,0,sizeof(to_boy));
            if(!kase) kase++;
            else printf("
    ");
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                    scanf("%d",&a[i][j]);
                nxt[i]=1;
                q.push(i);
            }
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    int x;
                    scanf("%d",&x);
                    order[i][x]=j;
                }
            while(!q.empty())
            {
                int now=q.front();q.pop();
                int now_to=a[now][nxt[now]++];
                if(!to_boy[now_to]||order[now_to][now]<order[now_to][to_boy[now_to]]) 
                    solve(now,now_to);
                else q.push(now);
            }
            for(int i=1;i<=n;i++) printf("%d
    ",to_girl[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    asp.net Ctrl+回车提交
    Request.Form.Keys保存的是什么?
    让iframe子窗体取父窗体地址栏参数(querystring)
    Repeater在无数据记录时显示类似GridView空模板(EmptyDataTemplate)
    jQuery与javascript对照学习(获取父子前后元素)
    internet缓存Temp中的tmp文件
    C#反射遍历一个对象属性(小技巧)
    silverlight序列化反序列化,在c#其他程序反序列化
    Silverlight序列化反序列化(json.net)
    卸载oracle
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10851302.html
Copyright © 2011-2022 走看看