• 专题训练之最大流


    EK模板

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<vector>
     6 using namespace std;
     7 const int maxn=205;
     8 const int maxm=205;
     9 const int inf=1e9; 
    10 struct edge{
    11     int from,to,flow;
    12     edge(int u,int v,int f):from(u),to(v),flow(f) {}
    13 };
    14 int n,s,t;
    15 vector<edge>E;  //大小为边数的两倍 ,用于存边 
    16 vector<int>G[maxn]; //存每个点对应的边 
    17 int a[maxn],p[maxn]; //a代表每个点的流出量,p用于记录进入该点的那条边的编号 
    18 
    19 void init()  //初始化 
    20 {
    21     for ( int i=0;i<n;i++ ) G[i].clear();
    22     E.clear();
    23 }
    24 
    25 void addedge(int from,int to,int flow)
    26 {
    27     E.push_back(edge(from,to,flow));
    28     E.push_back(edge(to,from,0));
    29     int m=E.size();
    30     G[from].push_back(m-2); 
    31     G[to].push_back(m-1);
    32 }
    33 
    34 int maxflow()
    35 {
    36     int flow=0;
    37     for ( ;; ) {
    38         memset(a,0,sizeof(a));
    39         a[s]=inf;
    40         queue<int>que;
    41         que.push(s);
    42         while ( !que.empty() ) {
    43             int u=que.front();
    44             que.pop();
    45             for ( int i=0;i<G[u].size();i++ ) {
    46                 int v=G[u][i];
    47                 edge& e=E[v];
    48                 if ( e.flow>0 && !a[e.to] ) {
    49                     p[e.to]=v;
    50                     a[e.to]=min(a[u],e.flow);
    51                     que.push(e.to);
    52                 }
    53             }
    54             if ( a[t] ) break;
    55         }
    56         if ( !a[t] ) break;
    57         for ( int u=t;u!=s;u=E[p[u]].from ) {
    58             E[p[u]].flow-=a[t];
    59             E[p[u]^1].flow+=a[t];
    60         }
    61         flow+=a[t];
    62     }
    63     return flow;
    64 }
    EK模板

    DINIC模板

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<vector>
     6 using namespace std;
     7 const int maxn=205;
     8 const int maxm=205;
     9 const int inf=1e9;
    10 struct edge{
    11     int from,to,flow;
    12     edge(int u,int v,int f):from(u),to(v),flow(f) {}
    13 };
    14 int n,s,t;
    15 vector<edge>E;
    16 vector<int>G[maxn];
    17 bool vis[maxn]; //检测在bfs中能否到达终点t,每次BFS都要初始化一次 
    18 int d[maxn],cur[maxn]; //d代表点所在的层级,cur代表该点有多少条边已经考虑过了
    19 
    20 void init()  
    21 {
    22     for ( int i=0;i<=n;i++ ) G[i].clear();
    23     E.clear();
    24 }
    25 
    26 void addedge(int from,int to,int flow)
    27 {
    28     E.push_back(edge(from,to,flow));
    29     E.push_back(edge(to,from,0));
    30     int m=E.size();
    31     G[from].push_back(m-2);
    32     G[to].push_back(m-1);    
    33 } 
    34 
    35 bool BFS()
    36 {
    37     memset(vis,false,sizeof(vis));
    38     queue<int>que;
    39     que.push(s);
    40     d[s]=0;
    41     vis[s]=true;
    42     while ( !que.empty() ) {
    43         int u=que.front();
    44         que.pop();
    45         for ( int i=0;i<G[u].size();i++ ) {
    46             edge& e=E[G[u][i]];
    47             if ( !vis[e.to] && e.flow>0 ) {
    48                 d[e.to]=d[u]+1;
    49                 vis[e.to]=true;
    50                 que.push(e.to);
    51             }
    52         }
    53     }
    54     return vis[t];
    55 }
    56 
    57 int DFS(int u,int a) //a为目前为止所有边中的最小残量
    58 {
    59     if ( u==t || a==0 ) return a;
    60     int flow=0,f;
    61     for ( int& i=cur[u];i<G[u].size();i++ ) {
    62         edge& e=E[G[u][i]];
    63         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
    64             e.flow-=f;
    65             E[G[u][i]^1].flow+=f;
    66             flow+=f;
    67             a-=f;
    68             if ( a==0 ) break;
    69         }
    70     }
    71     return flow;
    72 }
    73 
    74 int maxflow()
    75 {
    76     int flow=0;
    77     while ( BFS() ) {
    78         memset(cur,0,sizeof(cur));
    79         flow+=DFS(s,inf);
    80     }
    81     return flow;
    82 }
    83  
    Dinic模板(残余网络)
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<vector>
     6 using namespace std;
     7 const int maxn=250;
     8 const int maxm=105;
     9 const int inf=1e9;
    10 int n,s,t;
    11 struct edge{
    12     int from,to,cap,flow;
    13     edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
    14 };
    15 vector<edge>E;
    16 vector<int>G[maxn];
    17 bool vis[maxn]; 
    18 int d[maxn],cur[maxn];
    19 
    20 void init()  
    21 {
    22     for ( int i=0;i<=n;i++ ) G[i].clear();
    23     E.clear();
    24 }
    25 
    26 void addedge(int from,int to,int cap)
    27 {
    28     E.push_back(edge(from,to,cap,0));
    29     E.push_back(edge(to,from,0,0));
    30     int m=E.size();
    31     G[from].push_back(m-2);
    32     G[to].push_back(m-1);    
    33 } 
    34 
    35 bool BFS()
    36 {
    37     memset(vis,false,sizeof(vis));
    38     queue<int>que;
    39     que.push(s);
    40     d[s]=0;
    41     vis[s]=true;
    42     while ( !que.empty() ) {
    43         int u=que.front();
    44         que.pop();
    45         for ( int i=0;i<G[u].size();i++ ) {
    46             edge& e=E[G[u][i]];
    47             if ( !vis[e.to] && (e.cap-e.flow)>0 ) {
    48                 d[e.to]=d[u]+1;
    49                 vis[e.to]=true;
    50                 que.push(e.to);
    51             }
    52         }
    53     }
    54     return vis[t];
    55 }
    56 
    57 int DFS(int u,int a) 
    58 {
    59     if ( u==t || a==0 ) return a;
    60     int flow=0,f;
    61     for ( int& i=cur[u];i<G[u].size();i++ ) {
    62         edge& e=E[G[u][i]];
    63         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0 ) {
    64             e.flow+=f;
    65             E[G[u][i]^1].flow-=f;
    66             flow+=f;
    67             a-=f;
    68             if ( a==0 ) break;
    69         }
    70     }
    71     return flow;
    72 }
    73 
    74 int maxflow()
    75 {
    76     int flow=0;
    77     while ( BFS() ) {
    78         memset(cur,0,sizeof(cur));
    79         flow+=DFS(s,inf);
    80     }
    81     return flow;
    82 }
    DINIC(有容量和流量)

    //注意初始化不要忘记

    HDOJ练习题

    1.(HDOJ1532) http://acm.hdu.edu.cn/showproblem.php?pid=1532 

    裸模板题

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<vector>
     6 using namespace std;
     7 const int maxn=205;
     8 const int maxm=205;
     9 const int inf=1e9; 
    10 struct edge{
    11     int from,to,flow;
    12     edge(int u,int v,int f):from(u),to(v),flow(f) {}
    13 };
    14 int n,s,t;
    15 vector<edge>E;  
    16 vector<int>G[maxn]; 
    17 int a[maxn],p[maxn]; 
    18 
    19 void init()  
    20 {
    21     for ( int i=0;i<n;i++ ) G[i].clear();
    22     E.clear();
    23 }
    24 
    25 void addedge(int from,int to,int flow)
    26 {
    27     E.push_back(edge(from,to,flow));
    28     E.push_back(edge(to,from,0));
    29     int m=E.size();
    30     G[from].push_back(m-2); 
    31     G[to].push_back(m-1);
    32 }
    33 
    34 int maxflow()
    35 {
    36     int flow=0;
    37     for ( ;; ) {
    38         memset(a,0,sizeof(a));
    39         a[s]=inf;
    40         queue<int>que;
    41         que.push(s);
    42         while ( !que.empty() ) {
    43             int u=que.front();
    44             que.pop();
    45             for ( int i=0;i<G[u].size();i++ ) {
    46                 int v=G[u][i];
    47                 edge& e=E[v];
    48                 if ( e.flow>0 && !a[e.to] ) {
    49                     p[e.to]=v;
    50                     a[e.to]=min(a[u],e.flow);
    51                     que.push(e.to);
    52                 }
    53             }
    54             if ( a[t] ) break;
    55         }
    56         if ( !a[t] ) break;
    57         for ( int u=t;u!=s;u=E[p[u]].from ) {
    58             E[p[u]].flow-=a[t];
    59             E[p[u]^1].flow+=a[t];
    60         }
    61         flow+=a[t];
    62     }
    63     return flow;
    64 }
    65 
    66 int main()
    67 {
    68     int i,j,k,x,y,z,m;
    69     while ( scanf("%d%d",&m,&n)!=EOF ) {
    70         init();
    71         for ( i=0;i<m;i++ ) {
    72             scanf("%d%d%d",&x,&y,&z);
    73             x--;y--;
    74             addedge(x,y,z);
    75         }
    76         s=0;
    77         t=n-1;
    78         int ans=maxflow();
    79         printf("%d
    ",ans);
    80     }
    81     return 0;
    82 } 
    HDOJ1532(EK)
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    const int maxn=205;
    const int maxm=205;
    const int inf=1e9;
    struct edge{
        int from,to,flow;
        edge(int u,int v,int f):from(u),to(v),flow(f) {}
    };
    int n,s,t;
    vector<edge>E;
    vector<int>G[maxn];
    bool vis[maxn];  
    int d[maxn],cur[maxn]; 
    
    void init()  
    {
        for ( int i=0;i<n;i++ ) G[i].clear();
        E.clear();
    }
    
    void addedge(int from,int to,int flow)
    {
        E.push_back(edge(from,to,flow));
        E.push_back(edge(to,from,0));
        int m=E.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);    
    } 
    
    bool BFS()
    {
        memset(vis,false,sizeof(vis));
        queue<int>que;
        que.push(s);
        d[s]=0;
        vis[s]=true;
        while ( !que.empty() ) {
            int u=que.front();
            que.pop();
            for ( int i=0;i<G[u].size();i++ ) {
                edge& e=E[G[u][i]];
                if ( !vis[e.to] && e.flow>0 ) {
                    d[e.to]=d[u]+1;
                    vis[e.to]=true;
                    que.push(e.to);
                }
            }
        }
        return vis[t];
    }
    
    int DFS(int u,int a) 
    {
        if ( u==t || a==0 ) return a;
        int flow=0,f;
        for ( int& i=cur[u];i<G[u].size();i++ ) {
            edge& e=E[G[u][i]];
            if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
                e.flow-=f;
                E[G[u][i]^1].flow+=f;
                flow+=f;
                a-=f;
                if ( a==0 ) break;
            }
        }
        return flow;
    } 
    
    int maxflow()
    {
        int flow=0;
        while ( BFS() ) {
            memset(cur,0,sizeof(cur));
            flow+=DFS(s,inf);
        }
        return flow;
    }
     
    int main()
    {
        int i,j,k,x,y,z,m;
        while ( scanf("%d%d",&m,&n)!=EOF ) {
            init();
            for ( i=0;i<m;i++ ) {
                scanf("%d%d%d",&x,&y,&z);
                x--;y--;
                addedge(x,y,z);
            }
            s=0;
            t=n-1;
            int ans=maxflow();
            printf("%d
    ",ans);
        }
        return 0;
    } 
    HDOJ1532(Dinic)

    2.(HDOJ3572) http://acm.hdu.edu.cn/showproblem.php?pid=3572

    题意:有n项任务和m台机器,对于任意任务i都有要求在[si,ei]这段时间中用掉pi小时才算完成任务。求是否可能完成任务

    分析:1.思考:考虑什么变量会是点,什么变量会成为边的容量,终点的条件和最大流有什么关系。

       2.对于源点和汇点:因为无论是对于项目还是机器还是时间来说在各自范围内等价的,没有任何的特殊,所有需要设置一个超级源点和超级汇点。

         3.对于任意任务i,都需要pi时间,就像是任务i是由pi个小任务组成的一样,而小任务和时间是等价的,所以是将所有的任务和时间看作点,类似于二分图,时间一边,任务一边,各自独立;

         4.因为机器的数量(动力)与工作的效率有关,即可以将机器的数量看作是源点到每个“时间”点的边的容量(类似于对于每个时间点来说能完成多少数量的小任务)。而每个任务到汇点的边的容量等于该任务所需的pi时间。而时间与任务之间边的容量与工作时间范围[si,ei]有关,每天对于需要的任务都只能提供1的小任务/时间/效率/动力。

         5.最终的判断条件就是所有任务所需要的时间(小任务)是否为maxflow

    注意:数组要开大一点,大小并只是任务数,而是任务数+时间。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn=2005;
      8 const int maxm=1005;
      9 const int inf=1e9;
     10 struct edge{
     11     int from,to,flow;
     12     edge(int u,int v,int f):from(u),to(v),flow(f) {}
     13 };
     14 struct node{
     15     int s,e,p;
     16 }arr[maxn];
     17 int n,s,t;
     18 vector<edge>E;
     19 vector<int>G[maxn];
     20 bool vis[maxn];
     21 int d[maxn],cur[maxn];
     22 
     23 void init()
     24 {
     25     for ( int i=0;i<=n;i++ ) G[i].clear();
     26     E.clear();
     27 }
     28 
     29 void addedge(int u,int v,int f)
     30 {
     31     E.push_back(edge(u,v,f));
     32     E.push_back(edge(v,u,0));
     33     int m=E.size();
     34     G[u].push_back(m-2);
     35     G[v].push_back(m-1);
     36 }
     37 
     38 bool BFS()
     39 {
     40     memset(vis,false,sizeof(vis));
     41     queue<int>que;
     42     que.push(s);
     43     vis[s]=true;
     44     d[s]=0;
     45     while ( !que.empty() ) {
     46         int u=que.front();
     47         que.pop();
     48         for ( int i=0;i<G[u].size();i++ ) {
     49             edge& e=E[G[u][i]];
     50             if ( !vis[e.to] && e.flow>0 ) {
     51                 d[e.to]=d[u]+1;
     52                 vis[e.to]=true;
     53                 que.push(e.to);
     54             }
     55         }
     56     }
     57     return vis[t];
     58 }
     59 
     60 int DFS(int u,int a)
     61 {
     62     if ( u==t || a==0 ) return a;
     63     int flow=0,f;
     64     for ( int& i=cur[u];i<G[u].size();i++ ) {
     65         edge& e=E[G[u][i]];
     66         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
     67             e.flow-=f;
     68             E[G[u][i]^1].flow+=f;
     69             flow+=f;
     70             a-=f;
     71             if ( a==0 ) break;
     72         }
     73     }
     74     return flow;
     75 }
     76 
     77 int maxflow()
     78 {
     79     int flow=0;
     80     while ( BFS() ) {
     81         memset(cur,0,sizeof(cur));
     82         flow+=DFS(s,inf);
     83     }
     84     return flow;
     85 }
     86 
     87 int main()
     88 {
     89     int T,i,j,k,m,N,M,h,ans,sum;
     90     scanf("%d",&T);
     91     for ( h=1;h<=T;h++ ) {
     92         scanf("%d%d",&N,&m);
     93         init();
     94         sum=0;
     95         n=0;
     96         for ( i=1;i<=N;i++ ) {
     97             scanf("%d%d%d",&arr[i].p,&arr[i].s,&arr[i].e);
     98             sum+=arr[i].p;
     99             n=max(arr[i].e,n);
    100         }
    101         n=n+N+1;
    102         s=0;
    103         t=n;
    104         for ( i=N+1;i<n;i++ ) addedge(s,i,m);
    105         for ( i=1;i<=N;i++ ) {
    106             addedge(i,n,arr[i].p);
    107             for ( j=arr[i].s;j<=arr[i].e;j++ ) addedge(j+N,i,1);
    108         }
    109         ans=maxflow();
    110         printf("Case %d: ",h);
    111         if ( ans==sum ) printf("Yes
    
    ");
    112         else printf("No
    
    ");
    113     }
    114     return 0;
    115 }
    HDOJ3572(Dinic)

    3.(HDOJ2732)http://acm.hdu.edu.cn/showproblem.php?pid=2732

    题意:给出n和d,n代表地图有几行,d代表蜥蜴能跳的最大距离。然后给出两个地图,第一个图为每根柱子能承受跳跃的次数,第二个图为蜥蜴所在的位置。

    错误思路:因为对于每根柱子来说同时只能有一只蜥蜴,所以考虑拆点,一根柱子能承受几次跳跃就拆成几个点。设置超级源点指向蜥蜴初始位置所在的点,容量为1.将那些可以直接跳出地图的点连向超级汇点,容量也为1,将那些能相互到达的点也连上容量为1的边。这样给出的第4个样例输出0没有办法满足

    正确的做法:http://blog.csdn.net/u013480600/article/details/38964749

    注意:1.输出格式,was和were,要不要加s

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 #include<cmath>
      7 using namespace std;
      8 const int maxn=805;
      9 const int maxm=25;
     10 const int inf=1e9;
     11 struct edge{
     12     int from,to,flow;
     13     edge(int u,int v,int f):from(u),to(v),flow(f) {}
     14 };
     15 struct node{
     16     int x;
     17     int y;
     18 }arr[maxn];
     19 int n,s,t;
     20 vector<edge>E;
     21 vector<int>G[maxn];
     22 bool vis[maxn];  
     23 int d[maxn],cur[maxn]; 
     24 char mp1[maxm][maxm],mp2[maxm][maxm];
     25 
     26 void init()  
     27 {
     28     for ( int i=0;i<=n;i++ ) G[i].clear();
     29     E.clear();
     30 }
     31 
     32 void addedge(int from,int to,int flow)
     33 {
     34     E.push_back(edge(from,to,flow));
     35     E.push_back(edge(to,from,0));
     36     int m=E.size();
     37     G[from].push_back(m-2);
     38     G[to].push_back(m-1);    
     39 } 
     40 
     41 bool BFS()
     42 {
     43     memset(vis,false,sizeof(vis));
     44     queue<int>que;
     45     que.push(s);
     46     d[s]=0;
     47     vis[s]=true;
     48     while ( !que.empty() ) {
     49         int u=que.front();
     50         que.pop();
     51         for ( int i=0;i<G[u].size();i++ ) {
     52             edge& e=E[G[u][i]];
     53             if ( !vis[e.to] && e.flow>0 ) {
     54                 d[e.to]=d[u]+1;
     55                 vis[e.to]=true;
     56                 que.push(e.to);
     57             }
     58         }
     59     }
     60     return vis[t];
     61 }
     62 
     63 int DFS(int u,int a) 
     64 {
     65     if ( u==t || a==0 ) return a;
     66     int flow=0,f;
     67     for ( int& i=cur[u];i<G[u].size();i++ ) {
     68         edge& e=E[G[u][i]];
     69         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
     70             e.flow-=f;
     71             E[G[u][i]^1].flow+=f;
     72             flow+=f;
     73             a-=f;
     74             if ( a==0 ) break;
     75         }
     76     }
     77     return flow;
     78 } 
     79 
     80 int maxflow()
     81 {
     82     int flow=0;
     83     while ( BFS() ) {
     84         memset(cur,0,sizeof(cur));
     85         flow+=DFS(s,inf);
     86     }
     87     return flow;
     88 }
     89 
     90 int dist(node a,node b)
     91 {
     92     return abs(a.x-b.x)+abs(a.y-b.y);
     93 }
     94 
     95 int main()
     96 {
     97     int T,i,j,k,h,x,y,z,N,M,d,u,v,l,cnt,dis,sum,ans;
     98     scanf("%d",&T);
     99     for ( h=1;h<=T;h++ ) {
    100         scanf("%d%d",&N,&d);
    101         init();
    102         for ( i=1;i<=N;i++ ) scanf("%s",mp1[i]+1);
    103         M=0;
    104         for ( i=1;mp1[1][i];i++ ) M++;
    105         s=0;
    106         n=N*M*2+1;
    107         t=n;
    108         cnt=0;
    109         sum=0;
    110         for ( i=1;i<=N;i++ ) scanf("%s",mp2[i]+1);
    111         for ( i=1;i<=N;i++ ) {
    112             for ( j=1;j<=M;j++ ) {
    113                 x=mp1[i][j]-'0';
    114                 u=(i-1)*M+j;
    115                 v=u+M*N; 
    116                 if ( x!=0 ) {
    117                     addedge(u,v,x);
    118                     if ( i<=d || j<=d || N-i<d || M-j<d ) addedge(v,t,inf);
    119                     arr[++cnt].x=i;
    120                     arr[cnt].y=j;
    121                 }
    122                 if ( mp2[i][j]=='L' ) {
    123                     addedge(s,u,1);
    124                     sum++;
    125                 }
    126             }
    127         }
    128         for ( i=1;i<=cnt;i++ ) {
    129             for ( j=1;j<=cnt;j++ ) {
    130                 u=(arr[i].x-1)*M+arr[i].y;
    131                 v=(arr[j].x-1)*M+arr[j].y;
    132                 if ( i==j ) continue;
    133                 dis=dist(arr[i],arr[j]);
    134                 if ( dis<=d ) addedge(u+M*N,v,inf);
    135             }
    136         }
    137         ans=sum-maxflow();
    138         if ( ans==0 ) printf("Case #%d: no lizard was left behind.
    ",h);
    139         else if ( ans==1 ) printf("Case #%d: 1 lizard was left behind.
    ",h);
    140         else printf("Case #%d: %d lizards were left behind.
    ",h,ans);
    141     }
    142     return 0;
    143 }
    HDOJ2732(Dinic)

    4.(HDOJ1569)http://acm.hdu.edu.cn/showproblem.php?pid=1569

    此题涉及二分图的最大点权独立集,补充知识:

     二分图最小点覆盖和最大独立集都可以转化为最大匹配求解。在这个基础上,把每个点赋予一个非负的权值,这两个问题就转化为:二分图最小点权覆盖和二分图最大点权独立集。

     二分图最小点权覆盖

    从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小。

    建模:原二分图中的边(u,v)替换为容量为INF的有向边(u,v),设立源点s和汇点t,将s和x集合中的点相连,容量为该点的权值;将y中的点同t相连,容量为该点的权值。在新图上求最大流,最大流量即为最小点权覆盖的权值和。

     二分图最大点权独立集

    在二分图中找到权值和最大的点集,使得它们之间两两没有边。其实它是最小点权覆盖的对偶问题。答案=总权值-最小点覆盖集。

    具体证明参考胡波涛的论文:https://wenku.baidu.com/view/986baf00b52acfc789ebc9a9.html

    分析:对于特殊图(网格形状)来说,某个点只与其四周的的几个点相连,建立联系(建为INF的边,原因是认为使其不为最小割)。将整个图进行黑白染色(按行坐标+纵坐标的奇偶染色),一种颜色的点和超级源点S建为点权的边,另一种颜色的点和超级汇点也建容量为点权的边。最后的值为总权值-最大流

    注意:1.数组不要开太小

    2.只有于S相连的点才访问他的四周然后建边,而不是任何颜色的点都可以建边的

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn=2550;
      8 const int maxm=55;
      9 const int inf=1e9;
     10 struct edge{
     11     int from,to,flow;
     12     edge(int u,int v,int f):from(u),to(v),flow(f) {}
     13 };
     14 int n,s,t;
     15 vector<edge>E;
     16 vector<int>G[maxn];
     17 bool vis[maxn];  
     18 int d[maxn],cur[maxn]; 
     19 int mp[maxm][maxm];
     20 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
     21 
     22 void init()  
     23 {
     24     for ( int i=0;i<=n;i++ ) G[i].clear();
     25     E.clear();
     26 }
     27 
     28 void addedge(int from,int to,int flow)
     29 {
     30     E.push_back(edge(from,to,flow));
     31     E.push_back(edge(to,from,0));
     32     int m=E.size();
     33     G[from].push_back(m-2);
     34     G[to].push_back(m-1);    
     35 } 
     36 
     37 bool BFS()
     38 {
     39     memset(vis,false,sizeof(vis));
     40     queue<int>que;
     41     que.push(s);
     42     d[s]=0;
     43     vis[s]=true;
     44     while ( !que.empty() ) {
     45         int u=que.front();
     46         que.pop();
     47         for ( int i=0;i<G[u].size();i++ ) {
     48             edge& e=E[G[u][i]];
     49             if ( !vis[e.to] && e.flow>0 ) {
     50                 d[e.to]=d[u]+1;
     51                 vis[e.to]=true;
     52                 que.push(e.to);
     53             }
     54         }
     55     }
     56     return vis[t];
     57 }
     58 
     59 int DFS(int u,int a) 
     60 {
     61     if ( u==t || a==0 ) return a;
     62     int flow=0,f;
     63     for ( int& i=cur[u];i<G[u].size();i++ ) {
     64         edge& e=E[G[u][i]];
     65         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
     66             e.flow-=f;
     67             E[G[u][i]^1].flow+=f;
     68             flow+=f;
     69             a-=f;
     70             if ( a==0 ) break;
     71         }
     72     }
     73     return flow;
     74 } 
     75 
     76 int maxflow()
     77 {
     78     int flow=0;
     79     while ( BFS() ) {
     80         memset(cur,0,sizeof(cur));
     81         flow+=DFS(s,inf);
     82     }
     83     return flow;
     84 }
     85 
     86 int main()
     87 {
     88     int N,M,i,j,k,x,y,z,u,v,sum,ans,dx,dy;
     89     while ( scanf("%d%d",&N,&M)!=EOF ) {
     90         init();
     91         sum=0;
     92         for ( i=1;i<=N;i++ ) {
     93             for ( j=1;j<=M;j++ ) {
     94                 scanf("%d",&mp[i][j]);
     95                 sum+=mp[i][j];
     96             }
     97         }
     98         s=0;
     99         n=N*M+1;
    100         t=n;
    101         for ( i=1;i<=N;i++ ) {
    102             for ( j=1;j<=M;j++ ) {
    103                 u=(i-1)*M+j;
    104                 if ( (i+j)%2==0 ) {
    105                     addedge(s,u,mp[i][j]);
    106                     for ( k=0;k<4;k++ ) {
    107                         x=i+dir[k][0];
    108                         y=j+dir[k][1];
    109                         if ( x>0 && x<=N && y>0 && y<=M ) {
    110                             v=(x-1)*M+y;
    111                             addedge(u,v,inf);
    112                         }
    113                     }    
    114                 }
    115                 else addedge(u,t,mp[i][j]);
    116             }
    117         }
    118         ans=sum-maxflow();
    119         printf("%d
    ",ans);
    120     }
    121     return 0;
    122 }
    HDOJ1569(Dinic)

    5.(HDOJ4289)http://acm.hdu.edu.cn/showproblem.php?pid=4289

    题意:输入N,M,N代表有多少点,M代表有多少边,起点为s,,终点为t。每个点都有一个费用表示的含义是切断和这个点的所有边。然后给出M条双向边。先求最小的费用使得s不能到达t

    分析:考虑到点有限制,所以采用拆点的方法,将每个点拆成两个点,中间连一条容量为点权的边。同时起点为s前一个点,终点为t后一个点(这样可以保证s,t也可被消灭)。然后连通两个点的一条无向边,分别表示为x->y+N和y->x+N容量都为inf的边,即一个点的出点和另一个点的入点相连,因为对边没有任何的限制,所以将边设置为inf。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn=505;
      8 const int maxm=205;
      9 const int inf=1e9;
     10 struct edge{
     11     int from,to,flow;
     12     edge(int u,int v,int f):from(u),to(v),flow(f) {}
     13 };
     14 int n,s,t;
     15 vector<edge>E;
     16 vector<int>G[maxn];
     17 bool vis[maxn]; 
     18 int d[maxn],cur[maxn]; 
     19 
     20 void init()  
     21 {
     22     for ( int i=0;i<=n;i++ ) G[i].clear();
     23     E.clear();
     24 }
     25 
     26 void addedge(int from,int to,int flow)
     27 {
     28     E.push_back(edge(from,to,flow));
     29     E.push_back(edge(to,from,0));
     30     int m=E.size();
     31     G[from].push_back(m-2);
     32     G[to].push_back(m-1);    
     33 } 
     34 
     35 bool BFS()
     36 {
     37     memset(vis,false,sizeof(vis));
     38     queue<int>que;
     39     que.push(s);
     40     d[s]=0;
     41     vis[s]=true;
     42     while ( !que.empty() ) {
     43         int u=que.front();
     44         que.pop();
     45         for ( int i=0;i<G[u].size();i++ ) {
     46             edge& e=E[G[u][i]];
     47             if ( !vis[e.to] && e.flow>0 ) {
     48                 d[e.to]=d[u]+1;
     49                 vis[e.to]=true;
     50                 que.push(e.to);
     51             }
     52         }
     53     }
     54     return vis[t];
     55 }
     56 
     57 int DFS(int u,int a) 
     58 {
     59     if ( u==t || a==0 ) return a;
     60     int flow=0,f;
     61     for ( int& i=cur[u];i<G[u].size();i++ ) {
     62         edge& e=E[G[u][i]];
     63         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
     64             e.flow-=f;
     65             E[G[u][i]^1].flow+=f;
     66             flow+=f;
     67             a-=f;
     68             if ( a==0 ) break;
     69         }
     70     }
     71     return flow;
     72 } 
     73 
     74 int maxflow()
     75 {
     76     int flow=0;
     77     while ( BFS() ) {
     78         memset(cur,0,sizeof(cur));
     79         flow+=DFS(s,inf);
     80     }
     81     return flow;
     82 }
     83 
     84 int main()
     85 {
     86     int N,i,j,k,x,y,z,M,ans;
     87     while ( scanf("%d%d",&N,&M)!=EOF ) {
     88         scanf("%d%d",&x,&y);
     89         s=x-1;
     90         t=y-1+N;
     91         n=2*N;
     92         init();
     93         for ( i=0;i<N;i++ ) {
     94             scanf("%d",&x);
     95             addedge(i,i+N,x);
     96         }
     97         for ( i=1;i<=M;i++ ) {
     98             scanf("%d%d",&x,&y);
     99             x--;y--;
    100             addedge(x+N,y,inf);
    101             addedge(y+N,x,inf);
    102         }
    103         ans=maxflow();
    104         printf("%d
    ",ans);
    105     }
    106     return 0;
    107  } 
    HDOJ4289(Dinci)

    6.(HDOJ3605)http://acm.hdu.edu.cn/showproblem.php?pid=3605

    题意:地球上有n个人,有m个星球,每个人对每个星球都有适应/不适应两种情况,只有适应才能移居到那个星球。每个星球所能承受的人也是有限的。问是否所有人都能够移民。

    分析:初看以为是个裸模板,类似二分图,地球上的人一边,星球一边,第i个人对j个星球适应就连一条容量为1的边,起点和每个人连一条容量为1的边,每个星球和终点连一条容量为该星球承受最大人数的边。但是因为n很大所有一定会超时,这时发现m<=10,所以所有的点最多只有1024种情况,所以采用类似于状态压缩的办法进行缩点,将适应情况一样的人放在一个点,这样点的最大数量为1023(人数集合)+2(起点和终点)+10(星球个数)=1035,在这个范围内还是可以求解的。同时注意当有人对所有星期都不适应的时候直接输出NO。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    const int maxn=1200;
    const int maxm=205;
    const int inf=1e9;
    struct edge{
        int from,to,flow;
        edge(int u,int v,int f):from(u),to(v),flow(f) {}
    };
    int n,s,t;
    vector<edge>E;
    vector<int>G[maxn];
    bool vis[maxn]; 
    int d[maxn],cur[maxn],p[maxn],num[12]; 
    
    void init()  
    {
        for ( int i=0;i<=n;i++ ) G[i].clear();
        E.clear();
    }
    
    void addedge(int from,int to,int flow)
    {
        E.push_back(edge(from,to,flow));
        E.push_back(edge(to,from,0));
        int m=E.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);    
    } 
    
    bool BFS()
    {
        memset(vis,false,sizeof(vis));
        queue<int>que;
        que.push(s);
        d[s]=0;
        vis[s]=true;
        while ( !que.empty() ) {
            int u=que.front();
            que.pop();
            for ( int i=0;i<G[u].size();i++ ) {
                edge& e=E[G[u][i]];
                if ( !vis[e.to] && e.flow>0 ) {
                    d[e.to]=d[u]+1;
                    vis[e.to]=true;
                    que.push(e.to);
                }
            }
        }
        return vis[t];
    }
    
    int DFS(int u,int a) 
    {
        if ( u==t || a==0 ) return a;
        int flow=0,f;
        for ( int& i=cur[u];i<G[u].size();i++ ) {
            edge& e=E[G[u][i]];
            if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
                e.flow-=f;
                E[G[u][i]^1].flow+=f;
                flow+=f;
                a-=f;
                if ( a==0 ) break;
            }
        }
        return flow;
    } 
    
    int maxflow()
    {
        int flow=0;
        while ( BFS() ) {
            memset(cur,0,sizeof(cur));
            flow+=DFS(s,inf);
        }
        return flow;
    }
    
    int main()
    {
        int N,M,i,j,k,x,y,z,m,ans;
        while ( scanf("%d%d",&N,&m)!=EOF ) {
            memset(p,0,sizeof(p));
            for ( i=0;i<N;i++ ) {
                x=0;
                for ( j=0;j<m;j++ ) {
                    scanf("%d",&y);
                    if ( y==1 ) x+=(1<<j);
                }
                p[x]++;
            }
            for ( i=0;i<m;i++ ) scanf("%d",&num[i]);
            if ( p[0]!=0 ) {
                printf("NO
    ");
                continue;
            }
            s=0;
            n=(1<<m)+m;
            t=n;
            init();
            for ( i=1;i<(1<<m);i++ ) addedge(s,i,p[i]);
            for ( i=0;i<m;i++ ) addedge((1<<m)+i,t,num[i]);
            for ( i=1;i<(1<<m);i++ ) {
                for ( j=0;j<m;j++ ) {
                    if ( i&(1<<j) ) addedge(i,j+(1<<m),p[i]);
                }
            }
            ans=maxflow();
            if ( ans==N ) printf("YES
    ");
            else printf("NO
    ");
        }
        return 0;
    }
    HDOJ3605

    7.(HDOJ2883)http://acm.hdu.edu.cn/showproblem.php?pid=2883

    题意:有n个顾客,单位时间内能烧m块烤肉。对于第i个顾客有,si,ni,ei,ti,分别表示顾客在第si来(第一次提供烤肉已经是si+1了),ni表示顾客点的烤肉的数量,ei表示顾客在ei离开,ti表示该烤肉烧一块要ti的时间。现在求是否能满足所有客户的要求(判满流)。

    分析:本题实质上同2(HDOJ3572),那个题目中的天数对应这里的时间段(将某一时间段缩为一个点),那里的任务相当于这里的顾客。建边:起点于时间段建容量为pi*m的边(pi为该时间段的长度,m为单位时间烤肉的个数),人与终点建容量为ni*ti的边。因为这题si,ei的范围非常大,但是顾客数<=200,所有对应有至多200个起点,200个终点,将其离散化(方法是将所有起点和终点的时间都存入数组,从小到大进行排列,数组中相邻的不相同的两项构成一个时间区间)。对于顾客i来说,遍历所有的时间区间,当时间段被包含在[si,ei]之间则这两个点之间可以建一条为pi*m的边(注意这里一定是m,而不是min(ni,m),因为题目中给定一块肉也可以分开考,若没有这个条件,则对于第i个人来说一天最多烤ni块肉)。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn=1505;
      8 const int maxm=205;
      9 const int inf=1e9;
     10 struct edge{
     11     int from,to,flow;
     12     edge(int u,int v,int f):from(u),to(v),flow(f) {}
     13 };
     14 int n,s,t;
     15 vector<edge>E;
     16 vector<int>G[maxn];
     17 bool vis[maxn]; 
     18 int d[maxn],cur[maxn]; 
     19 struct node{
     20     int s;
     21     int n;
     22     int e;
     23     int t;
     24 }arr[maxn];
     25 struct node_{
     26     int x;
     27     int y;
     28     int p;
     29 }arr_[maxn];
     30 int num[maxn];
     31 
     32 void init()  
     33 {
     34     for ( int i=0;i<=n;i++ ) G[i].clear();
     35     E.clear();
     36 }
     37 
     38 void addedge(int from,int to,int flow)
     39 {
     40     E.push_back(edge(from,to,flow));
     41     E.push_back(edge(to,from,0));
     42     int m=E.size();
     43     G[from].push_back(m-2);
     44     G[to].push_back(m-1);    
     45 } 
     46 
     47 bool BFS()
     48 {
     49     memset(vis,false,sizeof(vis));
     50     queue<int>que;
     51     que.push(s);
     52     d[s]=0;
     53     vis[s]=true;
     54     while ( !que.empty() ) {
     55         int u=que.front();
     56         que.pop();
     57         for ( int i=0;i<G[u].size();i++ ) {
     58             edge& e=E[G[u][i]];
     59             if ( !vis[e.to] && e.flow>0 ) {
     60                 d[e.to]=d[u]+1;
     61                 vis[e.to]=true;
     62                 que.push(e.to);
     63             }
     64         }
     65     }
     66     return vis[t];
     67 }
     68 
     69 int DFS(int u,int a) 
     70 {
     71     if ( u==t || a==0 ) return a;
     72     int flow=0,f;
     73     for ( int& i=cur[u];i<G[u].size();i++ ) {
     74         edge& e=E[G[u][i]];
     75         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
     76             e.flow-=f;
     77             E[G[u][i]^1].flow+=f;
     78             flow+=f;
     79             a-=f;
     80             if ( a==0 ) break;
     81         }
     82     }
     83     return flow;
     84 } 
     85 
     86 int maxflow()
     87 {
     88     int flow=0;
     89     while ( BFS() ) {
     90         memset(cur,0,sizeof(cur));
     91         flow+=DFS(s,inf);
     92     }
     93     return flow;
     94 }
     95 
     96 int main()
     97 {
     98     int N,M,i,j,k,x,y,z,m,ans,sum,cnt;
     99     while ( scanf("%d%d",&N,&m)!=EOF ) {
    100         sum=0;
    101         for ( i=1;i<=N;i++ ) {
    102             scanf("%d%d%d%d",&x,&arr[i].n,&arr[i].e,&arr[i].t);
    103             arr[i].s=x;
    104             num[i]=arr[i].s;
    105             num[i+N]=arr[i].e;
    106             sum+=arr[i].n*arr[i].t;
    107         }
    108         sort(num+1,num+2*N+1);
    109         cnt=0;
    110         for ( i=1;i<2*N;i++ ) {
    111             if ( num[i]==num[i+1] ) continue;
    112             arr_[++cnt].x=num[i];
    113             arr_[cnt].y=num[i+1];
    114             arr_[cnt].p=num[i+1]-num[i];
    115         }
    116         s=0;
    117         n=N+cnt+1;
    118         t=n;
    119         init();
    120         for ( i=1;i<=cnt;i++ ) addedge(s,i,m*arr_[i].p);
    121         for ( i=1;i<=N;i++ ) addedge(i+cnt,t,arr[i].n*arr[i].t);
    122         for ( i=1;i<=N;i++ ) {
    123             for ( j=1;j<=cnt;j++ ) {
    124                 x=m;
    125                 if ( arr[i].s<=arr_[j].x && arr[i].e>=arr_[j].y ) addedge(j,i+cnt,arr_[j].p*x);
    126             }
    127         }
    128         ans=maxflow();
    129         if ( ans==sum ) printf("Yes
    ");
    130         else printf("No
    ");
    131     }
    132     return 0;
    133 }
    HDOJ2883

    8.(HDOJ4292)http://acm.hdu.edu.cn/showproblem.php?pid=4292

    挑战程序设计竞赛上的例题,将食物放一边,饮料放一边,将每个人拆成两个点。食物和起点之间连容量为食物数量的边,饮料和终点连容量为饮料数量的边,人和人之间连容量为1的边。人喜欢哪种食物就将食物和人的前一个点建1的边,人喜欢哪种饮料就将人后一个点和饮料建边。注意是谁指向谁

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn=1005;
      8 const int maxm=205;
      9 const int inf=1e9;
     10 struct edge{
     11     int from,to,flow;
     12     edge(int u,int v,int f):from(u),to(v),flow(f) {}
     13 };
     14 int n,s,t;
     15 vector<edge>E;
     16 vector<int>G[maxn];
     17 bool vis[maxn]; 
     18 int d[maxn],cur[maxn],D[maxn],F[maxn];
     19 char mp[maxn][maxn];
     20 
     21 void init()  
     22 {
     23     for ( int i=0;i<=n;i++ ) G[i].clear();
     24     E.clear();
     25 }
     26 
     27 void addedge(int from,int to,int flow)
     28 {
     29     E.push_back(edge(from,to,flow));
     30     E.push_back(edge(to,from,0));
     31     int m=E.size();
     32     G[from].push_back(m-2);
     33     G[to].push_back(m-1);    
     34 } 
     35 
     36 bool BFS()
     37 {
     38     memset(vis,false,sizeof(vis));
     39     queue<int>que;
     40     que.push(s);
     41     d[s]=0;
     42     vis[s]=true;
     43     while ( !que.empty() ) {
     44         int u=que.front();
     45         que.pop();
     46         for ( int i=0;i<G[u].size();i++ ) {
     47             edge& e=E[G[u][i]];
     48             if ( !vis[e.to] && e.flow>0 ) {
     49                 d[e.to]=d[u]+1;
     50                 vis[e.to]=true;
     51                 que.push(e.to);
     52             }
     53         }
     54     }
     55     return vis[t];
     56 }
     57 
     58 int DFS(int u,int a) 
     59 {
     60     if ( u==t || a==0 ) return a;
     61     int flow=0,f;
     62     for ( int& i=cur[u];i<G[u].size();i++ ) {
     63         edge& e=E[G[u][i]];
     64         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
     65             e.flow-=f;
     66             E[G[u][i]^1].flow+=f;
     67             flow+=f;
     68             a-=f;
     69             if ( a==0 ) break;
     70         }
     71     }
     72     return flow;
     73 } 
     74 
     75 int maxflow()
     76 {
     77     int flow=0;
     78     while ( BFS() ) {
     79         memset(cur,0,sizeof(cur));
     80         flow+=DFS(s,inf);
     81     }
     82     return flow;
     83 }
     84 
     85 int main()
     86 {
     87     int N,M,i,j,k,f,l,x,y,z,ans;
     88     while ( scanf("%d%d%d",&N,&f,&l)!=EOF ) {
     89         s=0;
     90         n=f+l+2*N+1;
     91         t=n;
     92         init();
     93         for ( i=1;i<=f;i++ ) {
     94             scanf("%d",&F[i]);
     95             addedge(s,i,F[i]);
     96         }
     97         for ( i=1;i<=l;i++ ) {
     98             scanf("%d",&D[i]);
     99             addedge(f+2*N+i,t,D[i]);
    100         }
    101         for ( i=1;i<=N;i++ ) addedge(i+f,i+f+N,1);
    102         for ( i=1;i<=N;i++ ) scanf("%s",mp[i]+1);
    103         for ( i=1;i<=N;i++ ) {
    104             for ( j=1;j<=f;j++ ) {
    105                 if ( mp[i][j]=='Y' ) addedge(j,f+i,1);
    106             }
    107         }
    108         for ( i=1;i<=N;i++ ) scanf("%s",mp[i]+1);
    109         for ( i=1;i<=N;i++ ) {
    110             for ( j=1;j<=l;j++ ) {
    111                 if ( mp[i][j]=='Y' ) addedge(N+f+i,j+f+2*N,1);
    112             }
    113         }
    114         ans=maxflow();
    115         printf("%d
    ",ans);
    116     }
    117     return 0;
    118 }
    HDOJ4292

    9.(HDOJ3416)http://acm.hdu.edu.cn/showproblem.php?pid=3416

    题意:求有几条最短路,每条路走过一次以后就不能再走。

    分析:刚开始没做出来。想的是利用类似最小费用流中的写法,将边与边的距离等效为费用,记录每次的费用,当某一次的费用与第一次不同时,则该次不是最短路。但是会超时

    正确的关键是:沿最短路进行最大流,只将最短路上的边(满足dist[u]==dist[v]+d(v,u))加入最大流的网络中

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn=1050;
      8 const int maxm=205;
      9 const int inf=1e9;
     10 struct Edge{
     11     int v;
     12     int cost;
     13     Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
     14 };
     15 vector<Edge>EE[maxn];
     16 struct edge{
     17     int from,to,flow;
     18     edge(int u,int v,int f):from(u),to(v),flow(f) {}
     19 };
     20 int n,s,t;
     21 vector<edge>E;
     22 vector<int>G[maxn];
     23 bool vis[maxn]; 
     24 int d[maxn],cur[maxn],dist[maxn]; 
     25 
     26 void addedge_(int u,int v,int w)
     27 {
     28     EE[u].push_back(Edge(v,w));
     29 }
     30 
     31 void SPFA()
     32 {
     33     memset(vis,false,sizeof(vis));
     34     for( int i=1;i<=n;i++ ) dist[i]=inf;
     35     vis[s]=true;
     36     dist[s]=0;
     37     queue<int>q;
     38     q.push(s);
     39     while ( !q.empty() ) {
     40         int u=q.front();
     41         q.pop();
     42         vis[u]=false;
     43         for ( int i=0;i<EE[u].size();i++ ) {
     44             int v=EE[u][i].v;
     45             if ( dist[v]>dist[u]+EE[u][i].cost ) {
     46                 dist[v]=dist[u]+EE[u][i].cost;
     47                 if ( !vis[v] ) {
     48                     vis[v]=true;
     49                     q.push(v);
     50                 }
     51             }
     52         }
     53     }
     54 }
     55 
     56 void init()  
     57 {
     58     for ( int i=0;i<=n;i++ ) G[i].clear();
     59     E.clear();
     60 }
     61 
     62 void addedge(int from,int to,int flow)
     63 {
     64     E.push_back(edge(from,to,flow));
     65     E.push_back(edge(to,from,0));
     66     int m=E.size();
     67     G[from].push_back(m-2);
     68     G[to].push_back(m-1);    
     69 } 
     70 
     71 bool BFS()
     72 {
     73     memset(vis,false,sizeof(vis));
     74     queue<int>que;
     75     que.push(s);
     76     d[s]=0;
     77     vis[s]=true;
     78     while ( !que.empty() ) {
     79         int u=que.front();
     80         que.pop();
     81         for ( int i=0;i<G[u].size();i++ ) {
     82             edge& e=E[G[u][i]];
     83             if ( !vis[e.to] && e.flow>0 ) {
     84                 d[e.to]=d[u]+1;
     85                 vis[e.to]=true;
     86                 que.push(e.to);
     87             }
     88         }
     89     }
     90     return vis[t];
     91 }
     92 
     93 int DFS(int u,int a) 
     94 {
     95     if ( u==t || a==0 ) return a;
     96     int flow=0,f;
     97     for ( int& i=cur[u];i<G[u].size();i++ ) {
     98         edge& e=E[G[u][i]];
     99         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.flow)))>0 ) {
    100             e.flow-=f;
    101             E[G[u][i]^1].flow+=f;
    102             flow+=f;
    103             a-=f;
    104             if ( a==0 ) break;
    105         }
    106     }
    107     return flow;
    108 }
    109 
    110 int maxflow()
    111 {
    112     int flow=0;
    113     while ( BFS() ) {
    114         memset(cur,0,sizeof(cur));
    115         flow+=DFS(s,inf);
    116     }
    117     return flow;
    118 }
    119  
    120 int main()
    121 {
    122     int T,i,j,k,x,y,z,m,u,v,dd,ans;
    123     scanf("%d",&T);
    124     while ( T-- ) {
    125         scanf("%d%d",&n,&m);
    126         for ( i=1;i<=n;i++ ) EE[i].clear();
    127         while ( m-- ) {
    128             scanf("%d%d%d",&x,&y,&z);
    129             addedge_(x,y,z);
    130         }
    131         scanf("%d%d",&s,&t);
    132         SPFA();
    133         init();
    134         for ( i=1;i<=n;i++ ) {
    135             for ( j=0;j<EE[i].size();j++ ) {
    136                 v=EE[i][j].v;
    137                 dd=EE[i][j].cost;
    138                 if ( dist[i]+dd==dist[v] ) addedge(i,v,1);
    139             }
    140         }
    141         ans=maxflow();
    142         printf("%d
    ",ans);
    143     }
    144     return 0;
    145 }
    HDOJ3416

    10.(HDOJ3081)http://acm.hdu.edu.cn/showproblem.php?pid=3081

    题意:有N个女孩N个男孩,给出M对关系表示女孩选择男孩为男朋友,再给出f对关系,表示两个女孩之间为好朋友,男朋友可以互相选择

    错误想法:设立bool型数组line[i][j],为true表示第i个女生和第j个男生可以为男女朋友的关系,然后对于f对女生之间的关系采用并查集。最后s到女生的点建容量为N的边,男生到t建容量为N的边,男女之间有关系的建容量为1的边,跑最大流,最终答案为男生流向t中的边的流量的最小值。

    样例:1 3 4 0 1 2 2 1 2 3 3 2 答案应该是0,但用上述方法答案为1。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn=250;
      8 const int maxm=105;
      9 const int inf=1e9;
     10 bool line[maxn][maxn];
     11 int F[maxn];
     12 int n,s,t;
     13 struct edge{
     14     int from,to,cap,flow;
     15     edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
     16 };
     17 vector<edge>E;
     18 vector<int>G[maxn];
     19 bool vis[maxn]; 
     20 int d[maxn],cur[maxn];
     21 
     22 int find(int x)
     23 {
     24     if ( F[x]==-1 ) return x;
     25     return F[x]=find(F[x]);
     26 }
     27 
     28 void merge(int x,int y)
     29 {
     30     int fx=find(x);
     31     int fy=find(y);
     32     if ( fx!=fy ) F[fx]=fy;
     33 }
     34 
     35 void init()  
     36 {
     37     for ( int i=0;i<=n;i++ ) G[i].clear();
     38     E.clear();
     39 }
     40 
     41 void addedge(int from,int to,int cap)
     42 {
     43     E.push_back(edge(from,to,cap,0));
     44     E.push_back(edge(to,from,0,0));
     45     int m=E.size();
     46     G[from].push_back(m-2);
     47     G[to].push_back(m-1);    
     48 } 
     49 
     50 bool BFS()
     51 {
     52     memset(vis,false,sizeof(vis));
     53     queue<int>que;
     54     que.push(s);
     55     d[s]=0;
     56     vis[s]=true;
     57     while ( !que.empty() ) {
     58         int u=que.front();
     59         que.pop();
     60         for ( int i=0;i<G[u].size();i++ ) {
     61             edge& e=E[G[u][i]];
     62             if ( !vis[e.to] && (e.cap-e.flow)>0 ) {
     63                 d[e.to]=d[u]+1;
     64                 vis[e.to]=true;
     65                 que.push(e.to);
     66             }
     67         }
     68     }
     69     return vis[t];
     70 }
     71 
     72 int DFS(int u,int a) 
     73 {
     74     if ( u==t || a==0 ) return a;
     75     int flow=0,f;
     76     for ( int& i=cur[u];i<G[u].size();i++ ) {
     77         edge& e=E[G[u][i]];
     78         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0 ) {
     79             e.flow+=f;
     80             E[G[u][i]^1].flow-=f;
     81             flow+=f;
     82             a-=f;
     83             if ( a==0 ) break;
     84         }
     85     }
     86     return flow;
     87 }
     88 
     89 int maxflow()
     90 {
     91     int flow=0;
     92     while ( BFS() ) {
     93         memset(cur,0,sizeof(cur));
     94         flow+=DFS(s,inf);
     95     }
     96     return flow;
     97 }
     98 
     99 int main()
    100 {
    101     int i,j,k,x,y,z,N,M,T,f,ans,sum;
    102     scanf("%d",&T);
    103     while ( T-- ) {
    104         scanf("%d%d%d",&N,&M,&f);
    105         memset(F,-1,sizeof(F));
    106         memset(line,false,sizeof(line));
    107         while ( M-- ) {
    108             scanf("%d%d",&x,&y);
    109             line[x][y]=true;
    110         }
    111         while ( f-- ) {
    112             scanf("%d%d",&x,&y);
    113             merge(x,y);
    114         }
    115         s=0;
    116         n=2*N+1;
    117         t=n;
    118         init();
    119         for ( i=1;i<=N;i++ ) {
    120             for ( j=1;j<=N;j++ ) {
    121                 if ( i==j ) continue;
    122                 if ( find(i)==find(j) ) {
    123                     for ( k=1;k<=N;k++ ) {
    124                         if ( line[j][k] ) line[i][k]=true;
    125                     } 
    126                 }
    127             }
    128         }
    129         for ( i=1;i<=N;i++ ) {
    130             for ( j=1;j<=N;j++ ) {
    131                 if ( line[i][j] ) addedge(i,j+N,1); //注意一定要放在外面! 
    132             }
    133         }
    134         for ( i=1;i<=N;i++ ) {
    135             addedge(s,i,N);
    136             addedge(i+N,t,N);
    137         }
    138         sum=maxflow();
    139         ans=inf;
    140         for ( i=1+N;i<=2*N;i++ ) {
    141             for ( j=0;j<G[i].size();j++ ) {
    142                 edge& e=E[G[i][j]];
    143                 if ( e.flow>=0 ) ans=min(ans,e.flow);
    144             }
    145         }
    146         printf("%d
    ",ans);
    147     }
    148     return 0;
    149 }
    (HDOJ3081)错误代码

    正确思路:二分+并查集+最大流

    二分是在原流的基础上再进行最大流,而不是每次都从新开始。如何从本来已经跑过的最大流基础上继续进行?(待补充)

    每次从新开始不会TLE,二分枚举的s到女生边的容量,最后判断是否满流即可

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn=250;
      8 const int maxm=105;
      9 const int inf=1e9;
     10 bool line[maxn][maxn];
     11 int F[maxn];
     12 int n,s,t,N;
     13 struct edge{
     14     int from,to,cap,flow;
     15     edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
     16 };
     17 vector<edge>E;
     18 vector<int>G[maxn];
     19 bool vis[maxn]; 
     20 int d[maxn],cur[maxn];
     21 
     22 int find(int x)
     23 {
     24     if ( F[x]==-1 ) return x;
     25     return F[x]=find(F[x]);
     26 }
     27 
     28 void merge(int x,int y)
     29 {
     30     int fx=find(x);
     31     int fy=find(y);
     32     if ( fx!=fy ) F[fx]=fy;
     33 }
     34 
     35 void init()  
     36 {
     37     for ( int i=0;i<=n;i++ ) G[i].clear();
     38     E.clear();
     39 }
     40 
     41 void addedge(int from,int to,int cap)
     42 {
     43     E.push_back(edge(from,to,cap,0));
     44     E.push_back(edge(to,from,0,0));
     45     int m=E.size();
     46     G[from].push_back(m-2);
     47     G[to].push_back(m-1);    
     48 } 
     49 
     50 bool BFS()
     51 {
     52     memset(vis,false,sizeof(vis));
     53     queue<int>que;
     54     que.push(s);
     55     d[s]=0;
     56     vis[s]=true;
     57     while ( !que.empty() ) {
     58         int u=que.front();
     59         que.pop();
     60         for ( int i=0;i<G[u].size();i++ ) {
     61             edge& e=E[G[u][i]];
     62             if ( !vis[e.to] && (e.cap-e.flow)>0 ) {
     63                 d[e.to]=d[u]+1;
     64                 vis[e.to]=true;
     65                 que.push(e.to);
     66             }
     67         }
     68     }
     69     return vis[t];
     70 }
     71 
     72 int DFS(int u,int a) 
     73 {
     74     if ( u==t || a==0 ) return a;
     75     int flow=0,f;
     76     for ( int& i=cur[u];i<G[u].size();i++ ) {
     77         edge& e=E[G[u][i]];
     78         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0 ) {
     79             e.flow+=f;
     80             E[G[u][i]^1].flow-=f;
     81             flow+=f;
     82             a-=f;
     83             if ( a==0 ) break;
     84         }
     85     }
     86     return flow;
     87 }
     88 
     89 int maxflow()
     90 {
     91     int flow=0;
     92     while ( BFS() ) {
     93         memset(cur,0,sizeof(cur));
     94         flow+=DFS(s,inf);
     95     }
     96     return flow;
     97 }
     98 
     99 bool judge(int x)
    100 {
    101     int ans=maxflow();
    102     if ( ans==N*x ) return true;
    103     return false;
    104 }
    105 
    106 int main()
    107 {
    108     int i,j,k,x,y,z,M,T,f,ans,sum,l,r,mid,la;
    109     scanf("%d",&T);
    110     while ( T-- ) {
    111         scanf("%d%d%d",&N,&M,&f);
    112         memset(F,-1,sizeof(F));
    113         memset(line,false,sizeof(line));
    114         while ( M-- ) {
    115             scanf("%d%d",&x,&y);
    116             line[x][y]=true;
    117         }
    118         while ( f-- ) {
    119             scanf("%d%d",&x,&y);
    120             merge(x,y);
    121         }
    122         s=0;
    123         n=2*N+1;
    124         t=n;
    125         for ( i=1;i<=N;i++ ) {
    126             for ( j=1;j<=N;j++ ) {
    127                 if ( i==j ) continue;
    128                 if ( find(i)==find(j) ) {
    129                     for ( k=1;k<=N;k++ ) {
    130                         if ( line[j][k] ) line[i][k]=true;
    131                     } 
    132                 }
    133             }
    134         }
    135         for ( i=1;i<=N;i++ ) {
    136             for ( j=1;j<=N;j++ ) {
    137                 if ( line[i][j] ) addedge(i,j+N,1); 
    138             }
    139         }
    140         l=0;
    141         r=n+1;
    142         while ( r-l>1 ) {
    143             mid=(l+r)/2;
    144             init();
    145             for ( i=1;i<=N;i++ ) {
    146                 for ( j=1;j<=N;j++ ) {
    147                     if ( line[i][j] ) addedge(i,j+N,1); 
    148                 }
    149             }    
    150             for ( i=1;i<=N;i++ ) {
    151                 addedge(s,i,mid);
    152                 addedge(i+N,t,mid);
    153             }    
    154             if ( judge(mid) ) l=mid;
    155             else r=mid;
    156         }
    157         printf("%d
    ",l);
    158     }
    159     return 0;
    160 }
    HDOJ3081

    11.(HDOJ3338)http://acm.hdu.edu.cn/showproblem.php?pid=3338

    题意:对于每个黑格,如果黑格的左半部分有数代表该黑格以下的白格部分(到底或者到另一个黑格位置)之和为左半部分这个数值。同理可得右半部分代表往右。

    分析:“行进列出”是关键,分为3部分,左边放黑格的左半部分,右边放黑格的右半部分,中间放白格。s和左半部分相连,容量为对应的黑格左半部分的值;t和右半部分相连,值为对应黑格右半部分的值。对于白格,分别和对应行和列的黑格所在的编号相连,容量都是9(因为所填数字最大是9),同时这时候要设置流量为1(因为最小为1)。但是该思路的代码TLE了....

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<queue>
      6 using namespace std;
      7 const int maxn=150;
      8 const int maxm=10050;
      9 const int inf=1e9;
     10 int line[maxn][maxn];
     11 int row[maxn][maxn],col[maxn][maxn],ans[maxn][maxn];
     12 int N,M;
     13 int n,s,t;
     14 struct edge{
     15     int from,to,cap,flow;
     16     edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
     17 };
     18 vector<edge>E;
     19 vector<int>G[maxm];
     20 bool vis[maxm]; 
     21 int d[maxm],cur[maxm];
     22 
     23 void init()  
     24 {
     25     for ( int i=0;i<=n;i++ ) G[i].clear();
     26     E.clear();
     27 }
     28 
     29 void addedge(int from,int to,int cap,int flow)
     30 {
     31     E.push_back(edge(from,to,cap,flow));
     32     E.push_back(edge(to,from,0,-flow));
     33     int m=E.size();
     34     G[from].push_back(m-2);
     35     G[to].push_back(m-1);    
     36 } 
     37 
     38 bool BFS()
     39 {
     40     memset(vis,false,sizeof(vis));
     41     queue<int>que;
     42     que.push(s);
     43     d[s]=0;
     44     vis[s]=true;
     45     while ( !que.empty() ) {
     46         int u=que.front();
     47         que.pop();
     48         for ( int i=0;i<G[u].size();i++ ) {
     49             edge& e=E[G[u][i]];
     50             if ( !vis[e.to] && (e.cap-e.flow)>0 ) {
     51                 d[e.to]=d[u]+1;
     52                 vis[e.to]=true;
     53                 que.push(e.to);
     54             }
     55         }
     56     }
     57     return vis[t];
     58 }
     59 
     60 int DFS(int u,int a) 
     61 {
     62     if ( u==t || a==0 ) return a;
     63     int flow=0,f;
     64     for ( int& i=cur[u];i<G[u].size();i++ ) {
     65         edge& e=E[G[u][i]];
     66         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0 ) {
     67             e.flow+=f;
     68             E[G[u][i]^1].flow-=f;
     69             flow+=f;
     70             a-=f;
     71             if ( a==0 ) break;
     72         }
     73     }
     74     return flow;
     75 }
     76 
     77 int maxflow()
     78 {
     79     int flow=0;
     80     while ( BFS() ) {
     81         memset(cur,0,sizeof(cur));
     82         flow+=DFS(s,inf);
     83     }
     84     return flow;
     85 }
     86 
     87 int main()
     88 {
     89     char str[10];
     90     int i,j,k,x,y,z,num;
     91     while ( scanf("%d%d",&N,&M)!=EOF ) {
     92         memset(line,0,sizeof(line));
     93         memset(row,0,sizeof(row));
     94         memset(col,0,sizeof(col));
     95         memset(ans,0,sizeof(ans));
     96         for ( i=1;i<=N;i++ ) {
     97             for ( j=1;j<=M;j++ ) {
     98                 scanf("%s",str);
     99                 if ( str[0]=='.' ) {
    100                     line[i][j]=2;
    101                     continue;
    102                 }
    103                 if ( str[0]=='X' && str[4]=='X' ) continue;
    104                 line[i][j]=1;
    105                 if ( str[0]!='X' ) {
    106                     x=0;
    107                     for ( k=0;k<3;k++ ) {
    108                         y=str[k]-'0';
    109                         x=(x*10+y);
    110                     }
    111                     col[i][j]=x;
    112                 }
    113                 if ( str[4]!='X' ) {
    114                     x=0;
    115                     for ( k=4;k<7;k++ ) {
    116                         y=str[k]-'0';
    117                         x=(x*10+y);
    118                     }
    119                     row[i][j]=x;
    120                 }
    121             }
    122         }
    123         n=N*M*2+1;
    124         s=0;
    125         t=n;
    126         init();
    127         for ( i=1;i<=N;i++ ) {
    128             for ( j=1;j<=M;j++ ) {
    129                 if ( line[i][j]==1 ) {
    130                     if ( row[i][j]!=0 ) {
    131                         x=(i-1)*M+j;
    132                         num=0;
    133                         for ( k=j+1;k<=M;k++ ) {
    134                             y=(i-1)*M+k;
    135                             if ( line[i][k]==2 ) {
    136                                 num++;
    137                                 addedge(x,y,9,1);
    138                             }
    139                             else break;
    140                         }
    141                         addedge(s,x,row[i][j]-num,0);
    142                     }
    143                     if ( col[i][j]!=0 ) {
    144                         x=(i-1)*M+j+N*M;
    145                         num=0;
    146                         for ( k=i+1;k<=N;k++ ) {
    147                             y=(k-1)*M+j;
    148                             if ( line[k][j]==2 ) {
    149                                 addedge(y,x,9,1);
    150                                 num++;
    151                             }
    152                             else break;
    153                         }
    154                         addedge(x,t,col[i][j]-num,0);
    155                     }
    156                 }
    157             }
    158         }
    159         maxflow();
    160         for ( i=1;i<=N;i++ ) {
    161             for ( j=1;j<=M;j++ ) {
    162                 if ( line[i][j]==2 ) {
    163                     x=(i-1)*M+j;
    164                     ans[i][j]=E[G[x][0]].flow;
    165                 }
    166             }
    167         }
    168         for ( i=1;i<=N;i++ ) {
    169             for ( j=1;j<=M;j++ ) {
    170                 if ( j!=1 ) printf(" ");
    171                 if ( line[i][j]!=2 ) printf("_");
    172                 else printf("%d",ans[i][j]);
    173             }
    174             printf("
    ");
    175         }
    176     }
    177     return 0;
    178 }
    HDOJ3338(TLE)

     参考别人思路注意以下几点:1.对于至少为1,可以先令所有的最大容量都为8,最后所有格子都+1;

    注意:不要把所有的点都编两个号会TLE的,只对有用的点编号.很麻烦,但要耐心

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<queue>
      6 using namespace std;
      7 const int maxn=150;
      8 const int maxm=20050;
      9 const int inf=1e9;
     10 int line[maxn][maxn];
     11 int row[maxn][maxn],col[maxn][maxn],ans[maxn][maxn],num[maxn][maxn];
     12 int N,M;
     13 int n,s,t;
     14 struct edge{
     15     int from,to,cap,flow;
     16     edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
     17 };
     18 vector<edge>E;
     19 vector<int>G[maxm];
     20 bool vis[maxm]; 
     21 int d[maxm],cur[maxm],cnt,cntr,cntc;
     22 struct node{
     23     int x;
     24     int y;
     25 }arrr[maxm],arrc[maxm];
     26 
     27 void init()  
     28 {
     29     for ( int i=0;i<=n;i++ ) G[i].clear();
     30     E.clear();
     31 }
     32 
     33 void addedge(int from,int to,int cap)
     34 {
     35     E.push_back(edge(from,to,cap,0));
     36     E.push_back(edge(to,from,0,0));
     37     int m=E.size();
     38     G[from].push_back(m-2);
     39     G[to].push_back(m-1);    
     40 } 
     41 
     42 bool BFS()
     43 {
     44     memset(vis,false,sizeof(vis));
     45     queue<int>que;
     46     que.push(s);
     47     d[s]=0;
     48     vis[s]=true;
     49     while ( !que.empty() ) {
     50         int u=que.front();
     51         que.pop();
     52         for ( int i=0;i<G[u].size();i++ ) {
     53             edge& e=E[G[u][i]];
     54             if ( !vis[e.to] && (e.cap-e.flow)>0 ) {
     55                 d[e.to]=d[u]+1;
     56                 vis[e.to]=true;
     57                 que.push(e.to);
     58             }
     59         }
     60     }
     61     return vis[t];
     62 }
     63 
     64 int DFS(int u,int a) 
     65 {
     66     if ( u==t || a==0 ) return a;
     67     int flow=0,f;
     68     for ( int& i=cur[u];i<G[u].size();i++ ) {
     69         edge& e=E[G[u][i]];
     70         if ( d[u]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0 ) {
     71             e.flow+=f;
     72             E[G[u][i]^1].flow-=f;
     73             flow+=f;
     74             a-=f;
     75             if ( a==0 ) break;
     76         }
     77     }
     78     return flow;
     79 }
     80 
     81 int maxflow()
     82 {
     83     int flow=0;
     84     while ( BFS() ) {
     85         memset(cur,0,sizeof(cur));
     86         flow+=DFS(s,inf);
     87     }
     88     return flow;
     89 }
     90 
     91 int main()
     92 {
     93     char str[10];
     94     int i,j,k,x,y,z,num1,fx,fy,u,v;
     95     while ( scanf("%d%d",&N,&M)!=EOF ) {
     96         memset(line,0,sizeof(line));
     97         memset(row,0,sizeof(row));
     98         memset(col,0,sizeof(col));
     99         memset(ans,0,sizeof(ans));
    100         memset(num,0,sizeof(num));
    101         cnt=cntr=cntc=0;
    102         for ( i=1;i<=N;i++ ) {
    103             for ( j=1;j<=M;j++ ) {
    104                 scanf("%s",str);
    105                 if ( str[0]=='.' ) {
    106                     num[i][j]=++cnt;
    107                     line[i][j]=2;
    108                     continue;
    109                 }
    110                 if ( str[0]=='X' && str[4]=='X' ) continue;
    111                 line[i][j]=1;
    112                 if ( str[0]!='X' ) {
    113                     x=0;
    114                     for ( k=0;k<3;k++ ) {
    115                         y=str[k]-'0';
    116                         x=(x*10+y);
    117                     }
    118                     col[i][j]=x;
    119                     arrc[++cntc].x=i;
    120                     arrc[cntc].y=j;
    121                 }
    122                 if ( str[4]!='X' ) {
    123                     x=0;
    124                     for ( k=4;k<7;k++ ) {
    125                         y=str[k]-'0';
    126                         x=(x*10+y);
    127                     }
    128                     row[i][j]=x;
    129                     arrr[++cntr].x=i;
    130                     arrr[cntr].y=j;
    131                 }
    132             }
    133         }
    134         n=cnt+cntr+cntc+1;
    135         s=0;
    136         t=n;
    137         init();
    138         for ( i=1;i<=cntr;i++ ) {
    139             x=arrr[i].x;
    140             y=arrr[i].y;
    141             u=i;
    142             num1=0;
    143             for (  k=y+1;k<=M;k++ ) {
    144                 if ( line[x][k]==2 ) {
    145                     v=num[x][k]+cntr;
    146                     num1++;
    147                     addedge(u,v,8);
    148                 }
    149                 else break;
    150             }
    151             addedge(s,u,row[x][y]-num1);
    152         }
    153         for ( i=1;i<=cntc;i++ ) {
    154             x=arrc[i].x;
    155             y=arrc[i].y;
    156             u=i+cnt+cntr;
    157             num1=0;
    158             for ( k=x+1;k<=N;k++ ) {
    159                 if ( line[k][y]==2 ) {
    160                     v=num[k][y]+cntr;
    161                     num1++;
    162                     addedge(v,u,8);
    163                 }
    164                 else break;
    165             }
    166             addedge(u,t,col[x][y]-num1);
    167         }        
    168         maxflow();
    169         for ( i=1;i<=N;i++ ) {
    170             for ( j=1;j<=M;j++ ) {
    171                 if ( line[i][j]==2 ) {
    172                     x=cntr+num[i][j];
    173                     ans[i][j]=-E[G[x][0]].flow;
    174                 }
    175             }
    176         }
    177         for ( i=1;i<=N;i++ ) {
    178             for ( j=1;j<=M;j++ ) {
    179                 if ( j!=1 ) printf(" ");
    180                 if ( line[i][j]!=2 ) printf("_");
    181                 else printf("%d",ans[i][j]+1);
    182             }
    183             printf("
    ");
    184         }
    185     }
    186     return 0;
    187 }
    HDOJ3338

    12.(HDOJ2485)http://acm.hdu.edu.cn/showproblem.php?pid=2485

    两种思路:最小割+费用流和最小割+最大流(常见的错误思路)。

    A.最小割+最大流(常见的错误思路):该题大致同(HDOJ4289)去点使得起点和终点不可到达,为最小割的模型(对[2,n-1]的点进行拆点,建容量为1的边)。但是对于处理当最短路<=k的情况,这时候对于两点u,v来说当dis[s][u]+dis[v][t]+d(u,v)<k时才需要加入最大流中,这是本题的关键所在。这样的做法是错误的,只有刚好在最短路上的边才能添加进最大流中进行计算,否则会出现错误。如下面一个样例:

    8 10 5

    1 2

    2 3

    3 4

    4 5

    5 6

    6 8

    1 7

    7 8

    4 7

    7 4

    正确答案应该是1(去掉第7个点),而如果用这种方法会算出2。

    B.费用流。边的容量和上面相同,此时设置费用,对起点和终点以外的其他端点拆点后的边费用设为1,其他所有边的费用均为0。当总费用>k时结束算法。

    注意:1.对于某个点既要考虑到起点又要考虑到终点的距离,同时数据又不大时,先想到用floyd。

    2.将所有边保存下来,最后逐一访问看边和其两端的点是否满足条件

    3.注意区别最短路中的N和最大流中的n

    4.有关图论的题目可以自己画图手动模拟一下

    5.对于i,j两点的边容量大小没有关系,并不会影响到最后的结果。可以设置超级源点和汇点,也可以把1和2*N当作源点和汇点都没有关系。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 const int maxn=305;
      8 const int maxm=10050;
      9 const int inf=1e9;
     10 struct edge{
     11     int from,to,flow,cost;
     12     edge(int u,int v,int f,int c):from(u),to(v),flow(f),cost(c) {}
     13 };
     14 struct node{
     15     int x;
     16     int y;
     17 }arr[maxm];
     18 int n,s,t,m;
     19 long long cost;
     20 vector<edge>E;
     21 vector<int>G[maxn];
     22 bool vis[maxn];
     23 int d[maxn],p[maxn],a[maxn]; 
     24 
     25 void init()
     26 {
     27     for ( int i=0;i<=n;i++ ) G[i].clear();
     28     E.clear();
     29 }
     30 
     31 void addedge(int u,int v,int f,int c)
     32 {
     33     E.push_back(edge(u,v,f,c));
     34     E.push_back(edge(v,u,0,-c));
     35     int m=E.size();
     36     G[u].push_back(m-2);
     37     G[v].push_back(m-1);
     38 }
     39 
     40 bool bellmanford(int& flow)
     41 {
     42     for ( int i=0;i<=n;i++ ) d[i]=inf;
     43     memset(vis,false,sizeof(vis));
     44     d[s]=0;
     45     vis[s]=true;
     46     p[s]=0;
     47     a[s]=inf;
     48     queue<int>que;
     49     que.push(s);
     50     while ( !que.empty() ) {
     51         int u=que.front();
     52         que.pop();
     53         vis[u]=false;
     54         for ( int i=0;i<G[u].size();i++ ) {
     55             edge& e=E[G[u][i]];
     56             if ( e.flow>0 && d[e.to]>d[u]+e.cost ) {
     57                 d[e.to]=d[u]+e.cost;
     58                 p[e.to]=G[u][i];
     59                 a[e.to]=min(a[u],e.flow);
     60                 if ( !vis[e.to] ) {
     61                     que.push(e.to);
     62                     vis[e.to]=true;
     63                 }
     64             }
     65         }
     66     }
     67     if ( d[t]==inf ) return false;
     68     cost=(long long)d[t]*(long long)a[t];
     69     if( cost>m ) return false;
     70     flow+=a[t];
     71     for ( int u=t;u!=s;u=E[p[u]].from ) {
     72         E[p[u]].flow-=flow;
     73         E[p[u]^1].flow+=flow;
     74     }
     75     return true;
     76 }
     77 
     78 int mincost() 
     79 {
     80     int flow=0;
     81     cost=0;
     82     while ( bellmanford(flow));
     83     return flow;
     84 }
     85 
     86 int main()
     87 {
     88     int N,i,j,k,x,y,z,M,ans;
     89     while ( scanf("%d%d%d",&N,&M,&m)!=EOF && (N+M+m) ) {
     90         s=0;
     91         n=2*N+1;
     92         t=n;
     93         init();
     94         for ( i=0;i<M;i++ ) {
     95             scanf("%d%d",&x,&y);
     96             arr[i].x=x;
     97             arr[i].y=y;
     98             addedge(x+N,y,1,1);
     99         }
    100         addedge(s,1,inf,0);
    101         addedge(2*N,t,inf,0);
    102         addedge(1,1+N,inf,0);
    103         addedge(N,2*N,inf,0);
    104         for ( i=2;i<N;i++ ) addedge(i,i+N,1,0);
    105         ans=mincost();
    106         printf("%d
    ",ans);
    107     }
    108     return 0;
    109 }
    HDOJ2485
  • 相关阅读:
    Chrome自带恐龙小游戏的源码研究(四)
    Chrome自带恐龙小游戏的源码研究(三)
    Chrome自带恐龙小游戏的源码研究(二)
    Chrome自带恐龙小游戏的源码研究(一)
    使用HTML5制作简单的RPG游戏
    EventListener中的handleEvent
    canvas drawImage方法不显示图片的解决方案
    canvas转盘抽奖的实现(二)
    股市高手的领悟
    《最伟大的投资习惯》读书笔记
  • 原文地址:https://www.cnblogs.com/HDUjackyan/p/8596015.html
Copyright © 2020-2023  润新知