• 匈牙利算法(codevs2776)


    type node=^link;
     link=record
       des:longint;
       next:node;
        end;
    
    var
     n,m,i,t,num:longint;
     p:node;
     nd:array[1..200] of node;
     mat:array[1..200] of longint;
     vis:array[1..200]  of boolean;
     sel:array[1..200] of longint;
    
     function find(po:longint):boolean;
     var
      p:node;
       begin
         p:=nd[po];
         while p<>nil do
          begin
            if vis[p^.des]=false then
              begin
                vis[p^.des]:=true;
                if sel[p^.des]=0 then
                  begin
                    sel[p^.des]:=po;
                    mat[po]:=p^.des;
                    exit(true);
                  end else
                if find(sel[p^.des])=true then
                  begin
                    sel[p^.des]:=po;
                    mat[po]:=p^.des;
                    exit(true);
                  end;
              end;
             p:=p^.next;
          end;
         exit(false);
       end;
    
      begin
    
        read(n,m);
    
        for i:=1 to n do
          begin
            read(t);
            while t<>0 do
              begin
                new(p);p^.next:=nd[t];p^.des:=i;nd[t]:=p;
                read(t);
              end;
          end;
    
        for i:=1 to m do
          if mat[i]=0 then
            begin
              fillchar(vis,sizeof(vis),0);
              if find(i) then inc(num);
            end;
    
        writeln(num);
    
      end.

    c++

    -------------------------------------------------------------------------------------------

    BZOJ1059

    #include <cstdio>
      
      int nd[201],next[100001],bt[201],des[100001],sel[201],mat[201],n,cnt;
    
      int dfs(int po){
          for (int p=nd[po];p!=-1;p=next[p])
            if (bt[des[p]]==0){
            bt[des[p]]=1;
          if (sel[des[p]]==-1||dfs(sel[des[p]])){
              sel[des[p]]=po;
              mat[po]=des[p];
              return(1);
          }
        }
        return(0);
      }
    
      int Hung(){
          for (int i=1;i<=n;i++) sel[i]=-1;
          
          for (int i=1;i<=n;i++){
            for (int j=1;j<=n;j++) bt[j]=0;
            if (!dfs(i)) return(0);    
        }
        
        return(1);
      }
      
      void addedge(int x,int y){
          next[++cnt]=nd[x];des[cnt]=y;nd[x]=cnt;
      }
    
      int main(){
          int T;
          scanf("%d",&T);
          while (T--){
            cnt=0;
            scanf("%d",&n);
            
            for (int i=1;i<=n;i++) nd[i]=-1;
            for (int i=1;i<=n;i++)
              for (int j=1;j<=n;j++){
                int t;
                scanf("%d",&t);    
                if (t) addedge(i,j);
            }
            
          if (Hung()) printf("Yes
    ");else printf("No
    ");    
        }
      }

    另外,

    最小点覆盖数=最大匹配数 
    最大独立集=顶点数-最大匹配数
    最小路径覆盖数 = 顶点数 - 最大匹配数

    _____________________________________________

    BZOJ1443

    确定一个点是否为匹配的必选点,后手走匹配边

    (确定必选边BZOJ2140)

    #include <cstdio>
    #include <map>
    using namespace std;
    
      map <int,int> mp;
    
      const int dir[4][2]={{-1,0},{0,-1},{0,1},{1,0}};
    
      int n,m,b[101][101],ndx[10101],ndy[10101],next[1000001],des[1000001];
      int vis[10101],sel[10101],mat[10101],dfstim,xcnt,ycnt,cnt,ans[10101][2];
      char st[110];
    
      void addedgex(int x,int y){
          next[++cnt]=ndx[x];des[cnt]=y;ndx[x]=cnt;
      }
      
      void addedgey(int x,int y){
          next[++cnt]=ndy[x];des[cnt]=y;ndy[x]=cnt;
      }
    
      int ok(int x,int y){
          return(x&&y&&x<=n&&y<=m&&b[x][y]);
      }
    
      int dfs(int po){
          for (int p=ndx[po];p!=-1;p=next[p])
            if (!vis[des[p]]){
              vis[des[p]]=1;
            if (sel[des[p]]==0||dfs(sel[des[p]])){
              mat[po]=des[p];sel[des[p]]=po;
              return(1);    
            }    
          }
        return(0);  
      }
    
      int checkx(int po){
          vis[po]=dfstim;
          if (!mat[po]) return(1);
          for (int p=ndy[mat[po]];p!=-1;p=next[p])
            if (vis[des[p]]<dfstim)
              if (checkx(des[p])) return(1);
        return(0);
      }
      
      int checky(int po){
          vis[po]=dfstim;
          if (!sel[po]) return(1);
          for (int p=ndx[sel[po]];p!=-1;p=next[p])
            if (vis[des[p]]<dfstim)
              if (checky(des[p])) return(1);
        return(0);
      }
      
      int main(){
          scanf("%d%d",&n,&m);
          for (int i=1;i<=n;i++){
            scanf("%s",&st);
          for (int j=1;j<=m;j++)
            if (st[j-1]=='.'){
              b[i][j]=1;
              if (((i+j)&1)==0){
                mp[i*500+j]=++xcnt;
              }else{
                  mp[i*500+j]=++ycnt;
              }
            }    
        }
        
        for (int i=1;i<=xcnt;i++) ndx[i]=-1;
        for (int i=1;i<=ycnt;i++) ndy[i]=-1;
        for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
          if (b[i][j]&&(((i+j)&1)==0))
            for (int k=0;k<4;k++)
              if (ok(i+dir[k][0],j+dir[k][1]))
                addedgex(mp[i*500+j],mp[(i+dir[k][0])*500+j+dir[k][1]]),
                addedgey(mp[(i+dir[k][0])*500+j+dir[k][1]],mp[i*500+j]);
        
        for (int i=1;i<=xcnt;i++){
          for (int j=1;j<=ycnt;j++) vis[j]=0;
          dfs(i);    
        }
        
        cnt=0;dfstim=1;
        for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
          if (b[i][j]){
              dfstim++;
              int po=mp[i*500+j];
              if (((i+j)&1)==0){
                if (checkx(po)){
                  cnt++;
                ans[cnt][0]=i;ans[cnt][1]=j;    
              }    
            }else
              if (checky(po)){
                    cnt++;
                ans[cnt][0]=i;ans[cnt][1]=j;    
              }    
          }
        
        if (cnt) printf("WIN
    ");else printf("LOSE
    ");
        for (int i=1;i<=cnt;i++)
          printf("%d %d
    ",ans[i][0],ans[i][1]);
      }

     ——————————————————————————————

    霍尔定理

    二部图G中的两部分顶点组成的集合分别为X, Y, X={X1, X2, X3,X4, .........,Xm} , Y={y1, y2, y3, y4 , .........,yn},G中有一组无公共点的边,一端恰好为组成X的点的充分必要条件是: X中的任意k个点至少与Y中的k个点相邻。

    TCO15 Round 1A Revmatching

    You have a weighted bipartite graph. Each partition contains n vertices numbered 0 through n-1. You are given the weights of all edges encoded into a vector <string> A with n elements, each containing n characters. For each i and j, A[i][j] is '0' if there is no edge between vertex i in the first partition and vertex j in the second partition. Otherwise, A[i][j] is between '1' and '9', inclusive, and the digit represents the weight of the corresponding edge.

    A perfect matching is a permutation p of 0 through n-1 such that for each i there is an edge (of any positive weight) between vertex i in the first partition and vertex p[i] in the second partition.

    Your goal is to have a graph that does not contain any perfect matching. You are allowed to delete edges from your current graph. You do not care about the number of edges you delete, only about their weights. More precisely, you want to reach your goal by deleting a subset of edges with the smallest possible total weight. Compute and return the total weight of deleted edges in an optimal solution.

    枚举每个X的子集,设其包含k个元素。断开若干点后使得Y中仅有k-1个元素。将断开点的价值求出后排序即可

        int smallest(vector <string> A){
          int n=A.size();
          
          int ans=1e9;
          for (int i=1;i<1<<n;i++){
               for (int j=1;j<=n;j++) sum[j]=0;
               for (int j=1;j<=n;j++)
                 if (i&(1<<(j-1))) 
                   for (int k=1;k<=n;k++)
                     sum[k]+=A[j-1][k-1]-'0';
            sort(sum+1,sum+n+1);
            int t=bitcount(i),tsum=0;
            for (int j=1;j<=n-t+1;j++) tsum+=sum[j];
            ans=min(ans,tsum);
          }
          return(ans);
        } 
  • 相关阅读:
    进程间通信(管道和有名管道)
    BAT面试需要什么样的程序员?
    深入剖析Redis系列: Redis哨兵模式与高可用集群
    七大进程间通信和线程同步
    详解Redis 的持久化机制--RDB和AOF
    大型网站技术架构演进
    Coding Standard(编程规范)
    @RequestBody,415Unsupported Media Type错误
    排序算法
    单例设计模式
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/5213016.html
Copyright © 2020-2023  润新知