专题训练之最大流

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\n",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\n",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\n\n");
112         else printf("No\n\n");
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.\n",h);
139         else if ( ans==1 ) printf("Case #%d: 1 lizard was left behind.\n",h);
140         else printf("Case #%d: %d lizards were left behind.\n",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\n",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\n",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\n");
            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\n");
        else printf("NO\n");
    }
    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\n");
130         else printf("No\n");
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\n",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\n",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\n",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\n",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("\n");
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("\n");
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\n",ans);
107     }
108     return 0;
109 }
HDOJ2485

 

posted @ 2018-03-18 16:32  HDU_jackyan  阅读(621)  评论(0编辑  收藏  举报