zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      先上题目传送门

      很明显的一个二分图,用匈牙利算法也可以轻松水过,但既然是网络流二十四题,当然是用网络流的算法才对嘛。

      数据很小,而且基本没什么思维难度,在外籍飞行员与英国飞行员之间连边形成一个图,然后建一个超级源点和一个超级汇点,再跑dinic或ISAP就可以了。

      至于输出配对的问题,只需要扫一边每一条正边(千万不能扫负边),判断改变的反向边容量是否大于0,如果大于0,就输出该边连的两个点。  

      很水吧?

      上代码(这里我用的dinic算法):

      

    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #define inf 1e9
    using namespace std;
    const int N=505;
    const int M=500050;
    int n,m,ans,start,endd;
    int head[N],size=1,cur[N];
    int depth[N];
    struct Node{
      int from,to,val,next;
    }edge[M<<1];
    inline int read()
    {
      char ch=getchar();int num=0;bool flag=false;
      while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
      while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
      return flag?-num:num;
    }
    inline void add(int x,int y,int z)
    {
      edge[++size].from=x;
      edge[size].to=y;
      edge[size].val=z;
      edge[size].next=head[x];
      head[x]=size;
    }
    inline void add_edge(int x,int y)
    {add(x,y,1);add(y,x,0);}
    void ready()
    {
      memset(head,-1,sizeof(head));
      m=read();n=read();
      start=0;endd=n+1;
      for(int i=1;i<=m;i++)
        add_edge(start,i);
      int x=read();int y=read();
      while(x!=-1&&y!=-1){
        add_edge(x,y);
        x=read();y=read();
      }
      for(int i=m+1;i<=n;i++)
        add_edge(i,endd);
    }
    inline bool bfs()
    {
      queue<int>team;
      memset(depth,0,sizeof(depth));
      depth[start]=1;team.push(start);
      while(!team.empty()){
        int x=team.front();team.pop();
        for(int i=head[x];i!=-1;i=edge[i].next){
          int y=edge[i].to;
          if(depth[y]==0&&edge[i].val>0){
        depth[y]=depth[x]+1;
        team.push(y);
          }
        }
      }
      return depth[endd]>0?true:false;
    }
    inline int dfs(int u,int flow)
    {
      if(u==endd||flow==0)return flow;
      for(int& i=cur[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(edge[i].val>0&&depth[v]==depth[u]+1){
          int ka=dfs(v,min(edge[i].val,flow));
          if(ka>0){
        edge[i].val-=ka;
        edge[i^1].val+=ka;
        return ka;
          }
        }
      }
      return 0;
    }
    void work()
    {
      while(bfs()){
        for(int i=start;i<=endd;i++)
          cur[i]=head[i];
        while(int d=dfs(start,inf))
          ans+=d;
      }
    }
    void solve()
    {
      if(ans==0)
        {cout<<"No Solution!";
          return ;}
      printf("%d
    ",ans);
      for(int i=0;i<=size;i+=2){
        int x=edge[i].from;
        int y=edge[i].to;
        if(x==start||y==start)
          continue;
        if(x==endd||y==endd)
          continue;
        if(edge[i^1].val>0){
          printf("%d %d
    ",x,y);
        }
      }
    }
    int main()
    {
      ready();
      work();
      solve();
      return 0;
    }
  • 相关阅读:
    http/ip 协议
    shell脚本
    LoadRunner脚本编写
    【WebGL】《WebGL编程指南》读书笔记——第6章
    【WebGL】《WebGL编程指南》读书笔记——第5章
    【WebGL】《WebGL编程指南》读书笔记——第4章
    【WebGL】《WebGL编程指南》读书笔记——第3章
    【WebGL】《WebGL编程指南》读书笔记——第2章
    【移动支付】.NET微信扫码支付接入(模式二-NATIVE)
    【学车】学车笔记-科目二
  • 原文地址:https://www.cnblogs.com/cytus/p/8084864.html
Copyright © 2011-2022 走看看