最大流

 

刚刚学了两个最大流算法Dinic和ISAP,很多地方不是很清楚=_=||

先刷些题练练吧

Drainage Ditches

 HDU - 1532 
题意:求1到n的最大流,裸题

可以说是模板题了,用Dinic做的

我把Lrj的模板改了下,个人不太喜欢用vector==

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define CLR(m,a) memset(m,a,sizeof(m))
  4 const int inf=0x3f3f3f3f;
  5 const int maxv=210;
  6 int n,m;
  7 struct Edge
  8 {
  9     int u,v,cap,flow;
 10     int nex;
 11 }e[maxv<<1];
 12 int head[maxv];
 13 int cnt=0;
 14 void init()
 15 {
 16     CLR(head,-1);
 17     cnt=0;
 18 }
 19 void add(int u,int v,int cap)
 20 {
 21     e[cnt].u=u;
 22     e[cnt].v=v;
 23     e[cnt].cap=cap;
 24     e[cnt].flow=0;
 25     e[cnt].nex=head[u];
 26     head[u]=cnt++;
 27 }
 28 
 29 int vis[maxv],d[maxv],cur[maxv];
 30 int s,t;
 31 int bfs()
 32 {
 33     CLR(vis,0);
 34     queue<int> q;
 35     q.push(s);
 36     d[s]=0;
 37     vis[s]=1;
 38     while(!q.empty())
 39     {
 40         int u=q.front();
 41         q.pop();
 42         for(int i=head[u];~i;i=e[i].nex)
 43         {
 44             int v=e[i].v;
 45             if(!vis[v]&&e[i].cap>e[i].flow)
 46             {
 47                 vis[v]=1;
 48                 d[v]=d[u]+1;
 49                 q.push(v);
 50             }
 51         }
 52     }
 53     return vis[t];
 54 }
 55 
 56 int dfs(int x,int a)
 57 {
 58     if(x==t||a==0) return a;
 59     int flow=0,f;
 60     for(int &i=cur[x];~i;i=e[i].nex)
 61     {
 62         int v=e[i].v;
 63         if(d[x]+1==d[v]&&(f=dfs(v,min(a,e[i].cap-e[i].flow)))>0)
 64         {
 65             e[i].flow+=f;
 66             e[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     {
 80         for(int i=0;i<n;i++) cur[i]=head[i];
 81         flow+=dfs(s,inf);
 82     }
 83     return flow;
 84 }
 85 
 86 int main()
 87 {
 88     while(scanf("%d%d",&m,&n)!=EOF)
 89     {
 90         init();
 91         int u,v,cap;
 92         for(int i=0;i<m;i++)
 93         {
 94             scanf("%d%d%d",&u,&v,&cap);
 95             u--;v--;
 96             add(u,v,cap);
 97             add(v,u,0);
 98         }
 99         s=0;t=n-1;  //
100         printf("%d\n",Maxflow());
101     }
102 }
View Code

 

Flow Problem

 HDU - 3549 
题意:求1到n的最大流,裸题

 本来想着练习一下ISPA

结果。。悲剧了一晚上。。。

代码里面有注释,关键点在更新m时判断一下d[v]是否可达,lrj的书里面没提到。。。

好像跟d的初始化有关。。。

再加上我用前向星存的边,出了点差错,单行调试了一上午才发现=_=||

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define CLR(m,a) memset(m,a,sizeof(m))
  4 const int inf=0x3f3f3f3f;
  5 const int maxv=20;
  6 const int maxe=1010;
  7 int n,m;
  8 struct Edge
  9 {
 10     int u,v,cap,flow;
 11     int nex;
 12 }e[maxe<<1];
 13 int head[maxv];
 14 int cnt=0;
 15 void init()
 16 {
 17     CLR(head,-1);
 18     cnt=0;
 19 }
 20 void add(int u,int v,int cap)
 21 {
 22     e[cnt].u=u;
 23     e[cnt].v=v;
 24     e[cnt].cap=cap;
 25     e[cnt].flow=0;
 26     e[cnt].nex=head[u];
 27     head[u]=cnt++;
 28 }
 29 
 30 int p[maxv];   // 可增广路上的上一条弧的编号
 31 int num[maxv]; // 和 t 的最短距离等于 i 的节点数量
 32 int cur[maxv];// 当前弧下标
 33 int d[maxv]; // 残量网络中节点 i 到汇点 t 的最短距离
 34 int vis[maxv];
 35 int s,t;
 36 
 37 // 预处理, 反向 BFS 构造 d 数组
 38 int bfs()
 39 {
 40     CLR(vis,0);
 41     CLR(d,-1);
 42     queue<int> q;
 43     while(!q.empty()) q.pop();
 44     q.push(t);
 45     vis[t]=1;
 46     d[t]=0;
 47     while(!q.empty())
 48     {
 49         int u=q.front();
 50         q.pop();
 51         for(int i=head[u];~i;i=e[i].nex)
 52         {
 53             int id=i&(-2);
 54             int v=e[id].u;
 55             if(!vis[v]&&e[id].cap>e[id].flow)
 56             {
 57                 vis[v]=1;
 58                 d[v]=d[u]+1;
 59                 q.push(v);
 60             }
 61         }
 62     }
 63     return vis[s];
 64 }
 65 
 66 //增广
 67 int augment()
 68 {
 69     int u=t,a=inf;
 70     while(u!=s)
 71     {
 72         int id=p[u];
 73         a=min(a,e[id].cap-e[id].flow);
 74         u=e[id].u;
 75     }
 76     u=t;
 77     while(u!=s)
 78     {
 79         int id=p[u];
 80         e[id].flow+=a;
 81         e[id^1].flow-=a;
 82         u=e[id].u;
 83     }
 84     return a;
 85 }
 86 
 87 int Maxflow()
 88 {
 89     bfs();
 90     int flow=0;
 91     CLR(num,0);
 92     for(int i=0;i<n;i++) num[d[i]]++;
 93     int u=s;
 94     for(int i=0;i<n;i++) cur[i]=head[i];
 95     while(d[s]<n)
 96     {
 97         if(u==t)
 98         {
 99             flow+=augment();
100             u=s;
101         }
102         int ok=0;
103         for(int i=cur[u];~i;i=e[i].nex)
104         {
105             int v=e[i].v;
106             if(e[i].cap>e[i].flow&&d[u]==d[v]+1)
107             {
108                 ok=1;
109                 p[v]=i;
110                 cur[u]=i;
111                 u=v;
112                 break;
113             }
114         }
115         if(!ok)
116         {
117             int m=n-1;
118             for(int i=head[u];~i;i=e[i].nex)
119             {
120                 int v=e[i].v;
121                 if(e[i].cap>e[i].flow&&d[v]!=-1) m=min(m,d[v]);
122             }
123             if(--num[d[u]]==0) break;  //gap优化
124             num[d[u]=m+1]++;
125             cur[u]=head[u];
126             if(u!=s) u=e[p[u]].u;
127         }
128     }
129     return flow;
130 }
131 
132 int main()
133 {
134     int tt;
135     int kase=0;
136     scanf("%d",&tt);
137     while(tt--)
138     {
139         init();
140         int u,v,cap;
141         scanf("%d%d",&n,&m);
142         for(int i=0;i<m;i++)
143         {
144             scanf("%d%d%d",&u,&v,&cap);
145             u--;v--;
146             add(u,v,cap);
147             add(v,u,0);
148         }
149         s=0;t=n-1;
150         printf("Case %d: %d\n",++kase,Maxflow());
151     }
152 }
View Code
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define CLR(m,a) memset(m,a,sizeof(m))
  4 const int inf=0x3f3f3f3f;
  5 const int maxv=20;
  6 const int maxe=1010;
  7 int n,m;
  8 struct Edge
  9 {
 10     int u,v,cap,flow;
 11     int nex;
 12 }e[maxe<<1];
 13 int head[maxv];
 14 int cnt=0;
 15 void init()
 16 {
 17     CLR(head,-1);
 18     cnt=0;
 19 }
 20 void add(int u,int v,int cap)
 21 {
 22     e[cnt].u=u;
 23     e[cnt].v=v;
 24     e[cnt].cap=cap;
 25     e[cnt].flow=0;
 26     e[cnt].nex=head[u];
 27     head[u]=cnt++;
 28 }
 29 
 30 int p[maxv];   // 可增广路上的上一条弧的编号
 31 int num[maxv]; // 和 t 的最短距离等于 i 的节点数量
 32 int cur[maxv];// 当前弧下标
 33 int d[maxv]; // 残量网络中节点 i 到汇点 t 的最短距离
 34 int vis[maxv];
 35 int s,t;
 36 
 37 // 预处理, 反向 BFS 构造 d 数组
 38 int bfs()
 39 {
 40     CLR(vis,0);
 41    // CLR(d,-1);   //!!!
 42     queue<int> q;
 43     while(!q.empty()) q.pop();
 44     q.push(t);
 45     vis[t]=1;
 46     d[t]=0;
 47     while(!q.empty())
 48     {
 49         int u=q.front();
 50         q.pop();
 51         for(int i=head[u];~i;i=e[i].nex)
 52         {
 53             int id=i&(-2);
 54             int v=e[id].u;
 55             if(!vis[v]&&e[id].cap>e[id].flow)
 56             {
 57                 vis[v]=1;
 58                 d[v]=d[u]+1;
 59                 q.push(v);
 60             }
 61         }
 62     }
 63     return vis[s];
 64 }
 65 
 66 //增广
 67 int augment()
 68 {
 69     int u=t,a=inf;
 70     while(u!=s)
 71     {
 72         int id=p[u];
 73         a=min(a,e[id].cap-e[id].flow);
 74         u=e[id].u;
 75     }
 76     u=t;
 77     while(u!=s)
 78     {
 79         int id=p[u];
 80         e[id].flow+=a;
 81         e[id^1].flow-=a;
 82         u=e[id].u;
 83     }
 84     return a;
 85 }
 86 
 87 int Maxflow()
 88 {
 89     bfs();
 90     int flow=0;
 91     CLR(num,0);
 92     for(int i=0;i<n;i++) num[d[i]]++;
 93     int u=s;
 94     for(int i=0;i<n;i++) cur[i]=head[i];
 95     while(d[s]<n)
 96     {
 97         if(u==t)
 98         {
 99             flow+=augment();
100             u=s;
101         }
102         int ok=0;
103         for(int i=cur[u];~i;i=e[i].nex)
104         {
105             int v=e[i].v;
106             if(e[i].cap>e[i].flow&&d[u]==d[v]+1)
107             {
108                 ok=1;
109                 p[v]=i;
110                 cur[u]=i;
111                 u=v;
112                 break;
113             }
114         }
115         if(!ok)
116         {
117             int m=n-1;
118             for(int i=head[u];~i;i=e[i].nex)
119             {
120                 int v=e[i].v;
121                 if(e[i].cap>e[i].flow/*&&d[v]!=-1*/) m=min(m,d[v]);   //关键点!!!注释掉就错啦
122             }
123             if(--num[d[u]]==0) break;  //gap优化
124             num[d[u]=m+1]++;
125             cur[u]=head[u];
126             if(u!=s) u=e[p[u]].u;
127         }
128     }
129     return flow;
130 }
131 
132 int main()
133 {
134     int tt;
135     int kase=0;
136     scanf("%d",&tt);
137     while(tt--)
138     {
139         init();
140         int u,v,cap;
141         scanf("%d%d",&n,&m);
142         for(int i=0;i<m;i++)
143         {
144             scanf("%d%d%d",&u,&v,&cap);
145             u--;v--;
146             add(u,v,cap);
147             add(v,u,0);
148         }
149         s=0;t=n-1;
150         printf("Case %d: %d\n",++kase,Maxflow());
151     }
152 }
153 /*
154 5 6
155 1 2 40
156 1 5 20
157 2 5 20
158 2 3 30
159 3 5 10
160 2 4 10
161 */
error

 补一个低效但相对简单易懂的算法Edmonds-Karp

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxv=20;
 4 const int maxe=1010;
 5 const int inf=0x3f3f3f3f;
 6 #define CLR(m,a) memset(m,a,sizeof(m))
 7 int n,m;
 8 struct Edge
 9 {
10     int u,v,cap,flow;
11     int nex;
12 }e[maxe<<1];
13 int head[maxv];
14 int cnt=0;
15 void init()
16 {
17     CLR(head,-1);
18     cnt=0;
19 }
20 void add(int u,int v,int cap)
21 {
22     e[cnt].u=u;
23     e[cnt].v=v;
24     e[cnt].flow=0;
25     e[cnt].cap=cap;
26     e[cnt].nex=head[u];
27     head[u]=cnt++;
28 }
29 int s,t;
30 int a[maxv],p[maxv];
31 int EK()
32 {
33     int flow=0;
34     for(;;)
35     {
36         CLR(a,0);
37         queue<int> q;
38         q.push(s);
39         a[s]=inf;
40         while(!q.empty())
41         {
42             int u=q.front();
43             q.pop();
44             for(int i=head[u];~i;i=e[i].nex)
45             {
46                 int v=e[i].v;
47                 if(!a[v]&&e[i].cap>e[i].flow)
48                 {
49                     p[v]=i;
50                     a[v]=min(a[u],e[i].cap-e[i].flow);
51                     q.push(v);
52                 }
53             }
54             if(a[t]) break;
55         }
56         if(!a[t]) break;
57         for(int u=t;u!=s;u=e[p[u]].u)
58         {
59             e[p[u]].flow+=a[t];
60             e[p[u]^1].flow-=a[t];
61         }
62         flow+=a[t];
63     }
64     return flow;
65 }
66 int main()
67 {
68     int tt;
69     int kase=0;
70     scanf("%d",&tt);
71     while(tt--)
72     {
73         init();
74         int u,v,cap;
75         scanf("%d%d",&n,&m);
76         for(int i=0;i<m;i++)
77         {
78             scanf("%d%d%d",&u,&v,&cap);
79             u--;v--;
80             add(u,v,cap);
81             add(v,u,0);
82         }
83         s=0;t=n-1;
84         printf("Case %d: %d\n",++kase,EK());
85     }
86 }
一般不用,效率低

 

Task Schedule

 HDU - 3572 
题意:要加工n个零件,每个零件要加工pi天,只能在si到ti之间加工,每天最多只能加工m个,问是否可以完工

加超级源和超级汇

本来建图能力就差,根本没想到

超级源到每一个零件连一条权重为pi的边,每个零件到可以加工的时间(每一天)连一条为1的边

时间(每一天)到超级汇连一条为m的边

其实还是比较好理解的

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define CLR(m,a) memset(m,a,sizeof(m))
  4 const int inf=0x3f3f3f3f;
  5 const int maxv=510;
  6 int n,m;
  7 struct Edge
  8 {
  9     int u,v,cap,flow;
 10     int nex;
 11 }e[(maxv*maxv<<1)+2010];
 12 int head[maxv<<1];
 13 int cnt=0;
 14 void init()
 15 {
 16     CLR(head,-1);
 17     cnt=0;
 18 }
 19 void add(int u,int v,int cap)
 20 {
 21     e[cnt].u=u;
 22     e[cnt].v=v;
 23     e[cnt].cap=cap;
 24     e[cnt].flow=0;
 25     e[cnt].nex=head[u];
 26     head[u]=cnt++;
 27 }
 28 int num[maxv<<1],d[maxv<<1],p[maxv<<1],vis[maxv<<1],cur[maxv<<1];
 29 int s,t;
 30 int bfs()
 31 {
 32     CLR(vis,0);
 33     CLR(d,-1);
 34     queue<int> q;
 35     q.push(t);
 36     d[t]=0;
 37     vis[t]=1;
 38     while(!q.empty())
 39     {
 40         int u=q.front();
 41         q.pop();
 42         for(int i=head[u];~i;i=e[i].nex)
 43         {
 44             int id=i&(-2);
 45             int v=e[id].u;
 46             if(!vis[v]&&e[id].cap>e[id].flow)
 47             {
 48                 vis[v]=1;
 49                 d[v]=d[u]+1;
 50                 q.push(v);
 51             }
 52         }
 53     }
 54     return vis[s];
 55 }
 56 int augment()
 57 {
 58     int u=t,a=inf;
 59     while(u!=s)
 60     {
 61         int id=p[u];
 62         a=min(a,e[id].cap-e[id].flow);
 63         u=e[id].u;
 64     }
 65     u=t;
 66     while(u!=s)
 67     {
 68         int id=p[u];
 69         e[id].flow+=a;
 70         e[id^1].flow-=a;
 71         u=e[id].u;
 72     }
 73     return a;
 74 }
 75 int ISAP()
 76 {
 77     bfs();
 78     int flow=0;
 79     CLR(num,0);
 80     for(int i=0;i<n;i++) num[d[i]]++;
 81     for(int i=0;i<n;i++) cur[i]=head[i];
 82     int u=s;
 83     while(d[s]<n)
 84     {
 85         if(u==t)
 86         {
 87             flow+=augment();
 88             u=s;
 89         }
 90         int ok=0;
 91         for(int i=cur[u];~i;i=e[i].nex)
 92         {
 93             int v=e[i].v;
 94             if(e[i].cap>e[i].flow&&d[u]==d[v]+1)
 95             {
 96                 ok=1;
 97                 p[v]=i;
 98                 cur[u]=i;
 99                 u=v;
100                 break;
101             }
102         }
103         if(!ok)
104         {
105             int m=n-1;
106             for(int i=head[u];~i;i=e[i].nex)
107                 if(e[i].cap>e[i].flow&&d[e[i].v]!=-1) m=min(m,d[e[i].v]);
108             if(--num[d[u]]==0) break;
109             num[d[u]=m+1]++;
110             cur[u]=head[u];
111             if(u!=s) u=e[p[u]].u;
112         }
113     }
114     return flow;
115 }
116 int main()
117 {
118     int tt;
119     int kase=0;
120     scanf("%d",&tt);
121     while(tt--)
122     {
123         init();
124         int si,pi,ei;
125         int sum=0;
126         int maxt=0;
127         s=0;
128         scanf("%d%d",&n,&m);
129         for(int i=1;i<=n;i++)
130         {
131             scanf("%d%d%d",&pi,&si,&ei);
132             maxt=max(maxt,ei);
133             sum+=pi;
134             add(s,i,pi);
135             add(i,s,0);
136             for(int j=si;j<=ei;j++)
137             {
138                 add(i,n+j,1);
139                 add(j+n,i,0);
140             }
141         }
142         t=n+maxt+1;
143         for(int i=1;i<=maxt;i++)
144         {
145             add(i+n,t,m);
146             add(t,i+n,0);
147         }
148         n=t+1;  //此处修改n值以适应模板
149         printf("Case %d: ",++kase);
150         if(ISAP()==sum) puts("Yes\n");
151         else puts("No\n");
152     }
153 }
View Code

 

Leapin' Lizards

 HDU - 2732

 题意:在一个网格状的区域内,有一些柱子,并且这些柱子有一定的允许跳跃次数,有的柱子上有人,人有最大跳跃距离(曼哈顿距离)

    问有几个人无法跳出此区域

还是不会建图啊,拆点!!!

增加超级源和超级汇

对于每一个人,从超级源到人连一条为1的边,对于任意两个可达的柱子,连一条无穷大的边,可跳出区域的柱子连一条无穷大的边到超级汇

然后拆点,把每个柱子拆成两个,连一条为跳跃次数的边。

拆点的意义在于限流!!!

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int inf=0x3f3f3f3f;
  4 const int maxv=1010;
  5 const int maxe=1000010;
  6 #define CLR(m,a) memset(m,a,sizeof(m))
  7 #define LL long long
  8 
  9 struct Edge
 10 {
 11     int u,v,cap,flow;
 12     int nex;
 13 }e[maxe<<1];
 14 int head[maxv];
 15 int cnt=0;
 16 void init()
 17 {
 18     CLR(head,-1);
 19     cnt=0;
 20 }
 21 void add(int u,int v,int cap)
 22 {
 23     e[cnt].u=u; e[cnt].v=v;
 24     e[cnt].cap=cap; e[cnt].flow=0;
 25     e[cnt].nex=head[u]; head[u]=cnt++;
 26 
 27     e[cnt].u=v; e[cnt].v=u;
 28     e[cnt].cap=0; e[cnt].flow=0;
 29     e[cnt].nex=head[v]; head[v]=cnt++;
 30 }
 31 char g1[25][25],g2[25][25];
 32 
 33 int n;
 34 int s,t;
 35 int p[maxv],cur[maxv],d[maxv],vis[maxv],num[maxv];
 36 void bfs()
 37 {
 38     CLR(vis,0);
 39     CLR(d,-1);
 40     queue<int> q;
 41     q.push(t);
 42     d[t]=0;
 43     vis[t]=1;
 44     while(!q.empty())
 45     {
 46         int u=q.front();
 47         q.pop();
 48         for(int i=head[u];~i;i=e[i].nex)
 49         {
 50             int id=i&(-2);
 51             int v=e[id].u;
 52             if(!vis[v]&&e[id].cap>e[id].flow)
 53             {
 54                 d[v]=d[u]+1;
 55                 vis[v]=1;
 56                 q.push(v);
 57             }
 58         }
 59     }
 60 }
 61 int augment()
 62 {
 63     int u=t,a=inf;
 64     while(u!=s)
 65     {
 66         int id=p[u];
 67         a=min(a,e[id].cap-e[id].flow);
 68         u=e[id].u;
 69     }
 70     u=t;
 71     while(u!=s)
 72     {
 73         int id=p[u];
 74         e[id].flow+=a;
 75         e[id^1].flow-=a;
 76         u=e[id].u;
 77     }
 78     return a;
 79 }
 80 int ISAP()
 81 {
 82     int flow=0;
 83     bfs();
 84     CLR(num,0);
 85     for(int i=0;i<n;i++){
 86         num[d[i]]++;
 87         cur[i]=head[i];
 88     }
 89     int u=s;
 90     while(d[s]<n){
 91         if(u==t){
 92             flow+=augment();
 93             u=s;
 94         }
 95         int ok=0;
 96         for(int i=cur[u];~i;i=e[i].nex){
 97             int v=e[i].v;
 98             if(e[i].cap>e[i].flow&&d[u]==d[v]+1){
 99                 ok=1;
100                 p[v]=i;
101                 cur[u]=i;
102                 u=v;
103                 break;
104             }
105         }
106         if(!ok){
107             int m=n-1;
108             for(int i=head[u];~i;i=e[i].nex){
109                 int v=e[i].v;
110                 if(e[i].cap>e[i].flow&&d[v]!=-1) m=min(m,d[v]);
111             }
112             if(--num[d[u]]==0) break;
113             num[d[u]=m+1]++;
114             cur[u]=head[u];
115             if(u!=s) u=e[p[u]].u;
116         }
117     }
118     return flow;
119 }
120 int main()
121 {
122     int tt;
123     int kase=0;
124     scanf("%d",&tt);
125     while(tt--){
126         init();
127         int r,c,dis;
128         int sum=0;
129         scanf("%d%d",&r,&dis);
130         for(int i=0;i<r;i++){
131             scanf("%s",g1[i]);
132         }
133         for(int i=0;i<r;i++){
134             scanf("%s",g2[i]);
135         }
136         c=strlen(g1[0]);
137         int py=r*c;  //拆点
138         s=0;
139         for(int i=0;i<r;i++){
140             for(int j=0;j<c;j++){
141                 int id=i*c+j+1;
142                 if(g2[i][j]=='L'){
143                     sum++;
144                     add(s,id,1);
145                 }
146                 if(g1[i][j]!='0'){
147                     add(id,id+py,g1[i][j]-'0');
148                     if(i-dis<0||i+dis>=r||j-dis<0||j+dis>=c){
149                         add(id+py,py*2+1,inf);
150                     }
151                     else{
152                         for(int x=0;x<r;x++)
153                         for(int y=0;y<c;y++){
154                             if(x==i&&y==j) continue;
155                             if(g1[x][y]!='0'){
156                                 if(abs(x-i)+abs(y-j)<=dis){
157                                     int newid=x*c+y+1;
158                                     add(id+py,newid,inf);
159                                 }
160                             }
161                         }
162                     }
163                 }
164             }
165         }
166         s=0;t=py*2+1;n=t+1; //!!!
167         int flow=ISAP();
168         printf("Case #%d: ",++kase);
169         if(flow==sum) puts("no lizard was left behind.");
170         else if(flow+1==sum) puts("1 lizard was left behind.");
171         else printf("%d lizards were left behind.\n",sum-flow);
172     }
173     return 0;
174 }
View Code

 

Kakuro Extension

 HDU - 3338 

TLE到爆炸!!!很烦!!!实在看不下去了。。。。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int inf=0x3f3f3f3f;
  4 const int maxv=200010;
  5 const int maxe=1000010;  //
  6 #define CLR(m,a) memset(m,a,sizeof(m))
  7 
  8 int n,m,s,t;
  9 int tot;
 10 struct Edge{
 11     int u,v,cap,flow;
 12     int nex;
 13 }e[maxe];
 14 int head[maxv];
 15 int cnt=0;
 16 void init(){
 17     CLR(head,-1);
 18     cnt=0;
 19 }
 20 void add(int u,int v,int cap)
 21 {
 22     e[cnt].u=u; e[cnt].v=v;
 23     e[cnt].cap=cap; e[cnt].flow=0;
 24     e[cnt].nex=head[u]; head[u]=cnt++;
 25 
 26     e[cnt].u=v; e[cnt].v=u;
 27     e[cnt].cap=0; e[cnt].flow=0;
 28     e[cnt].nex=head[v]; head[v]=cnt++;
 29 }
 30 struct node{
 31     int id,cid,rid,sumc,sumr,type;
 32 }mp[105][105];
 33 int ans[105][105]; //记录该点的出边,便于输出
 34 
 35 int vis[maxv],cur[maxv],num[maxv],d[maxv],p[maxv];
 36 
 37 void bfs(){
 38     CLR(d,-1);
 39     CLR(vis,0);
 40     queue<int> q;
 41     q.push(t);
 42     d[t]=0;
 43     vis[t]=1;
 44     while(!q.empty()){
 45         int u=q.front();
 46         q.pop();
 47         for(int i=head[u];~i;i=e[i].nex){
 48             int id=i&(-2);
 49             int v=e[id].u;
 50             if(!vis[v]&&e[id].cap>e[id].flow){
 51                 vis[v]=1;
 52                 q.push(v);
 53                 d[v]=d[u]+1;
 54             }
 55         }
 56     }
 57 }
 58 int augment(){
 59     int a=inf,u=t;
 60     while(u!=s){
 61         int id=p[u];
 62         a=min(a,e[id].cap-e[id].flow);
 63         u=e[id].u;
 64     }
 65     u=t;
 66     while(u!=s){
 67         int id=p[u];
 68         e[id].flow+=a;
 69         e[id^1].flow-=a;
 70         u=e[id].u;
 71     }
 72     return a;
 73 }
 74 int ISAP(){
 75     bfs();
 76     int flow=0;
 77     CLR(num,0);
 78     for(int i=0;i<tot;i++){
 79         num[d[i]]++;
 80         cur[i]=head[i];
 81     }
 82     int u=s;
 83     while(d[s]<tot)
 84     {
 85         if(u==t)
 86         {
 87             flow+=augment();
 88             u=s;
 89         }
 90         int ok=0;
 91         for(int i=cur[u];~i;i=e[i].nex){
 92             int v=e[i].v;
 93             if(e[i].cap>e[i].flow&&d[u]==d[v]+1){
 94                 ok=1;
 95                 cur[u]=i;
 96                 p[v]=i;
 97                 u=v;
 98                 break;
 99             }
100         }
101         if(!ok){
102             int m=tot-1;
103             if(--num[d[u]]==0) break;
104             for(int i=head[u];~i;i=e[i].nex){
105                 int v=e[i].v;
106                 if(e[i].cap>e[i].flow&&d[v]!=-1) m=min(m,d[v]);
107             }
108             num[d[u]=m+1]++;
109             cur[u]=head[u];
110             if(u!=s) u=e[p[u]].u;
111         }
112     }
113     return flow;
114 }
115 
116 int main(){
117     while(scanf("%d%d",&n,&m)!=EOF){
118         init();
119         char c[10];
120         int rowcnt=0,colcnt=0,white=0;
121         for(int i=0;i<n;i++)
122         for(int j=0;j<m;j++){
123             scanf("%s",c);
124             if(c[3]=='X') continue;
125             else if(c[3]=='.'){
126                 white++;
127                 mp[i][j].type=2;
128                 mp[i][j].id=white;
129             }
130             else{
131                 mp[i][j].type=1;
132                 int num;
133                 if(c[0]!='X'){
134                     num=(c[0]-'0')*100+(c[1]-'0')*10+c[2]-'0';
135                     colcnt++;
136                     mp[i][j].cid=colcnt;
137                     mp[i][j].sumc=num;
138                 }
139                 if(c[4]!='X'){
140                     num=(c[4]-'0')*100+(c[5]-'0')*10+c[6]-'0';
141                     rowcnt++;
142                     mp[i][j].rid=rowcnt;
143                     mp[i][j].sumr=num;
144                 }
145             }
146         }
147         s=0;t=white+rowcnt+colcnt+1;
148         tot=t+1;
149         //编点,white<colcnt<rowcnt
150         for(int i=0;i<n;i++)
151         for(int j=0;j<m;j++){
152             if(mp[i][j].type==1){
153                 if(mp[i][j].sumc>0){ //如果列有数字
154                     int id=mp[i][j].cid+white;
155                     for(int k=i+1;k<n;k++){
156                         if(mp[k][j].type==2){
157                             add(id,mp[k][j].id,8);
158                             mp[i][j].sumc--;
159                         }
160                         else break;
161                     }
162                     add(s,id,mp[i][j].sumc);
163                 }
164                 if(mp[i][j].sumr>0){
165                     int id=mp[i][j].rid+white+colcnt;
166                     for(int k=j+1;k<m;k++){
167                         if(mp[i][k].type==2){
168                             ans[i][k]=cnt;
169                             add(mp[i][k].id,id,8);
170                             mp[i][j].sumr--;
171                         }
172                         else break;
173                     }
174                     add(id,t,mp[i][j].sumr);
175                 }
176             }
177         }
178         int temp=ISAP();
179        // cout<<temp<<endl;
180         for(int i=0;i<n;i++){
181             for(int j=0;j<m;j++){
182                 if(mp[i][j].type==2){
183                     printf("%d%c",e[ans[i][j]].flow+1,j==m-1?'\n':' ');
184                 }
185                 else printf("_%c",j==m-1?'\n':' ');
186             }
187         }
188     }
189     return 0;
190 }
TLE

 终于过了,,初始化坑死人啊。。。。

记不清被初始化坑多少次了=_=||

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int inf=0x3f3f3f3f;
  4 const int maxv=200010;
  5 const int maxe=1000010;  //
  6 #define CLR(m,a) memset(m,a,sizeof(m))
  7 
  8 int n,m,s,t;
  9 int tot;
 10 struct Edge{
 11     int u,v,cap,flow;
 12     int nex;
 13 }e[maxe];
 14 int head[maxv];
 15 int cnt=0;
 16 void init(){
 17     CLR(head,-1);
 18     cnt=0;
 19 }
 20 void add(int u,int v,int cap)
 21 {
 22     e[cnt].u=u; e[cnt].v=v;
 23     e[cnt].cap=cap; e[cnt].flow=0;
 24     e[cnt].nex=head[u]; head[u]=cnt++;
 25 
 26     e[cnt].u=v; e[cnt].v=u;
 27     e[cnt].cap=0; e[cnt].flow=0;
 28     e[cnt].nex=head[v]; head[v]=cnt++;
 29 }
 30 struct node{
 31     int id,cid,rid,sumc,sumr,type;
 32 }mp[110][110];
 33 int ans[110][110]; //记录该点的出边,便于输出
 34 
 35 int vis[maxv],cur[maxv],num[maxv],d[maxv],p[maxv];
 36 
 37 void bfs(){
 38     CLR(d,-1);
 39     CLR(vis,0);
 40     queue<int> q;
 41     q.push(t);
 42     d[t]=0;
 43     vis[t]=1;
 44     while(!q.empty()){
 45         int u=q.front();
 46         q.pop();
 47         for(int i=head[u];~i;i=e[i].nex){
 48             int id=i&(-2);
 49             int v=e[id].u;
 50             if(!vis[v]&&e[id].cap>e[id].flow){
 51                 vis[v]=1;
 52                 q.push(v);
 53                 d[v]=d[u]+1;
 54             }
 55         }
 56     }
 57 }
 58 int augment(){
 59     int a=inf,u=t;
 60     while(u!=s){
 61         int id=p[u];
 62         a=min(a,e[id].cap-e[id].flow);
 63         u=e[id].u;
 64     }
 65     u=t;
 66     while(u!=s){
 67         int id=p[u];
 68         e[id].flow+=a;
 69         e[id^1].flow-=a;
 70         u=e[id].u;
 71     }
 72     return a;
 73 }
 74 int ISAP(){
 75     bfs();
 76     int flow=0;
 77     CLR(num,0);
 78     for(int i=0;i<tot;i++){
 79         if(d[i]!=-1) num[d[i]]++;
 80         cur[i]=head[i];
 81     }
 82     int u=s;
 83     while(d[s]<tot)
 84     {
 85         if(u==t)
 86         {
 87             flow+=augment();
 88             u=s;
 89         }
 90         int ok=0;
 91         for(int i=cur[u];~i;i=e[i].nex){
 92             int v=e[i].v;
 93             if(e[i].cap>e[i].flow&&d[u]==d[v]+1){
 94                 ok=1;
 95                 cur[u]=i;
 96                 p[v]=i;
 97                 u=v;
 98                 break;
 99             }
100         }
101         if(!ok){
102             int m=tot-1;
103             for(int i=head[u];~i;i=e[i].nex){
104                 int v=e[i].v;
105                 if(e[i].cap>e[i].flow&&d[v]!=-1) m=min(m,d[v]);
106             }
107             if(--num[d[u]]==0) break;
108             num[d[u]=m+1]++;
109             cur[u]=head[u];
110             if(u!=s) u=e[p[u]].u;
111         }
112     }
113     return flow;
114 }
115 
116 int main(){
117     while(scanf("%d%d",&n,&m)==2){
118         init();
119         char c[8];
120         int rowcnt=0,colcnt=0,white=0;
121         for(int i=0;i<n;i++)
122         for(int j=0;j<m;j++){
123             scanf("%s",c);
124             if(c[3]=='X') {
125                 mp[i][j].type=0;
126                 continue;
127             }
128             else if(c[3]=='.'){
129                 white++;
130                 mp[i][j].type=2;
131                 mp[i][j].id=white;
132             }
133             else{
134                 mp[i][j].type=1;
135                  mp[i][j].sumc=0;
136                   mp[i][j].sumr=0;
137                 int num;
138                 if(c[0]!='X'){
139                     num=(c[0]-'0')*100+(c[1]-'0')*10+c[2]-'0';
140                     colcnt++;
141                     mp[i][j].cid=colcnt;
142                     mp[i][j].sumc=num;
143                 }
144                 if(c[4]!='X'){
145                     num=(c[4]-'0')*100+(c[5]-'0')*10+c[6]-'0';
146                     rowcnt++;
147                     mp[i][j].rid=rowcnt;
148                     mp[i][j].sumr=num;
149                 }
150             }
151         }
152         s=0;t=white+rowcnt+colcnt+1;
153         tot=t+1;
154         //编点,white<colcnt<rowcnt
155         for(int i=0;i<n;i++)
156         for(int j=0;j<m;j++){
157             if(mp[i][j].type==1){
158                 if(mp[i][j].sumc>0){ //如果列有数字
159                     int id=mp[i][j].cid+white;
160                     for(int k=i+1;k<n;k++){
161                         if(mp[k][j].type==2){
162                             add(id,mp[k][j].id,8);
163                             mp[i][j].sumc--;
164                         }
165                         else break;
166                     }
167                     add(s,id,mp[i][j].sumc);
168                 }
169                 if(mp[i][j].sumr>0){
170                     int id=mp[i][j].rid+white+colcnt;
171                     for(int k=j+1;k<m;k++){
172                         if(mp[i][k].type==2){
173                             ans[i][k]=cnt;
174                             add(mp[i][k].id,id,8);
175                             mp[i][j].sumr--;
176                         }
177                         else break;
178                     }
179                     add(id,t,mp[i][j].sumr);
180                 }
181             }
182         }
183         int temp=ISAP();
184         for(int i=0;i<n;i++){
185             for(int j=0;j<m;j++){
186                 if(mp[i][j].type==2){
187                     printf("%d%c",e[ans[i][j]].flow+1,j==m-1?'\n':' ');
188                 }
189                 else printf("_%c",j==m-1?'\n':' ');
190             }
191         }
192     }
193     return 0;
194 }
View Code

 

kebab

 HDU - 2883 

题意:n个任务,每个任务时间区间为[si,ei],工作量为ni*ti。单位时间最大工作量为m,求是否能完成任务。

和上面的hdu3572类似,区别就是这个工作可以分成ni份同时做,还有这个题的时间区间较大,先离散化,再把每个区间看成一个点。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define CLR(m,a) memset(m,a,sizeof(m))
  4 const int maxv=610;
  5 const int maxe=100010;
  6 const int inf=0x3f3f3f3f;
  7 struct Edge{
  8     int u,v,flow,cap;
  9     int nex;
 10     Edge(int u=0,int v=0,int flow=0,int cap=0,int nex=0):
 11         u(u),v(v),flow(flow),cap(cap),nex(nex){}
 12 }e[maxe<<2];
 13 int head[maxv];
 14 int cnt=0;
 15 void init(){
 16     CLR(head,-1);
 17     cnt=0;
 18 }
 19 void add(int u,int v,int cap){
 20     e[cnt]=Edge(u,v,0,cap,head[u]);
 21     head[u]=cnt++;
 22     e[cnt]=Edge(v,u,0,0,head[v]);
 23     head[v]=cnt++;
 24 }
 25 int si[maxv],ei[maxv],ti[maxv],ni[maxv];
 26 int des[maxv<<1];
 27 
 28 int d[maxv],num[maxv],cur[maxv],p[maxv];
 29 int vis[maxv];
 30 int s,t;
 31 int N;  //
 32 
 33 void bfs(){
 34     CLR(d,-1);
 35     CLR(vis,0);
 36     queue<int> q;
 37     q.push(t);
 38     d[t]=0;
 39     vis[t]=1;
 40     while(!q.empty()){
 41         int u=q.front();
 42         q.pop();
 43         for(int i=head[u];~i;i=e[i].nex){
 44             int id=i&(-2);
 45             int v=e[id].u;
 46             if(!vis[v]&&e[id].cap>e[id].flow){
 47                 vis[v]=1;
 48                 d[v]=d[u]+1;
 49                 q.push(v);
 50             }
 51         }
 52     }
 53     //
 54 }
 55 
 56 int augment(){
 57     int u=t,a=inf;
 58     while(u!=s){
 59         int id=p[u];
 60         a=min(a,e[id].cap-e[id].flow);
 61         u=e[id].u;
 62     }
 63     u=t;
 64     while(u!=s){
 65         int id=p[u];
 66         e[id].flow+=a;
 67         e[id^1].flow-=a;
 68         u=e[id].u;
 69     }
 70     return a;
 71 }
 72 
 73 int ISAP(){
 74     bfs();
 75     int flow=0;
 76     CLR(num,0);
 77     for(int i=0;i<N;i++){
 78         cur[i]=head[i];
 79         if(~d[i]) num[d[i]]++;
 80     }
 81     int u=s;
 82     while(d[s]<N){
 83         if(u==t){
 84             flow+=augment();
 85             u=s;
 86         }
 87         int ok=0;
 88         for(int i=cur[u];~i;i=e[i].nex){
 89             int v=e[i].v;
 90             if(d[u]==d[v]+1&&e[i].cap>e[i].flow){
 91                 p[v]=i;
 92                 ok=1;
 93                 cur[u]=i;
 94                 u=v;
 95                 break;
 96             }
 97         }
 98         if(!ok){
 99             int m=N-1;
100             for(int i=head[u];~i;i=e[i].nex){
101                 if(e[i].cap>e[i].flow&&~d[e[i].v]) m=min(m,d[e[i].v]);
102             }
103             if(--num[d[u]]==0) break;
104             num[d[u]=m+1]++;
105             cur[u]=head[u];
106             if(u!=s) u=e[p[u]].u;
107         }
108     }
109     return flow;
110 }
111 
112 int main(){
113     int n,m;
114     while(scanf("%d%d",&n,&m)!=EOF){
115         int sum=0;
116         int p=0;
117         init();
118         for(int i=1;i<=n;i++){
119             scanf("%d%d%d%d",&si[i],&ni[i],&ei[i],&ti[i]);
120             des[p++]=si[i];
121             des[p++]=ei[i];
122             sum+=ni[i]*ti[i];
123         }
124         sort(des,des+p);
125         p=unique(des,des+p)-des;
126         s=0,t=n+p;
127         for(int i=1;i<=n;i++){
128             add(s,i,ti[i]*ni[i]);
129         }
130         for(int i=1;i<p;i++){
131             add(n+i,t,(des[i]-des[i-1])*m);
132             for(int j=1;j<=n;j++){
133                 if(si[j]<=des[i-1]&&ei[j]>=des[i])
134                     add(j,n+i,inf);
135             }
136         }
137         N=t+1;
138         int flow=ISAP();
139         if(flow==sum) puts("Yes");
140         else puts("No");
141     }
142 }
View Code

 

Escape

 HDU - 3605 

题意:n个人移民到m个星球。问是否能满足所有人的需求(即有的人不去某些星球)。

n有十万,m最大10,开始直接上模板做的,果断TLE,边数达到了1e6+。

注意到m最大是10,与n差距悬殊。考虑有多少种移民方案,每个星球选或者不选,所以最多1024种

以方案为点,该方案允许的人为边,再去建图

这样建图边数降到了1e4,过了~

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define CLR(m,a) memset(m,a,sizeof(m))
  4 const int maxv=1050;
  5 const int maxe=12000;
  6 const int inf=0x3f3f3f3f;
  7 struct Edge{
  8     int u,v,flow,cap;
  9     int nex;
 10     Edge(int u=0,int v=0,int flow=0,int cap=0,int nex=0):
 11         u(u),v(v),flow(flow),cap(cap),nex(nex){}
 12 }e[maxe<<1];
 13 int head[maxv];
 14 int cnt=0;
 15 void init(){
 16     CLR(head,-1);
 17     cnt=0;
 18 }
 19 void add(int u,int v,int cap){
 20     e[cnt]=Edge(u,v,0,cap,head[u]);
 21     head[u]=cnt++;
 22     e[cnt]=Edge(v,u,0,0,head[v]);
 23     head[v]=cnt++;
 24 }
 25 int vis[maxv],p[maxv],d[maxv],num[maxv],cur[maxv];
 26 int s,t;
 27 int N;
 28 
 29 void bfs(){
 30     CLR(d,-1);
 31     CLR(vis,0);
 32     queue<int> q;
 33     q.push(t);
 34     d[t]=0;
 35     vis[t]=1;
 36     while(!q.empty()){
 37         int u=q.front();
 38         q.pop();
 39         for(int i=head[u];~i;i=e[i].nex){
 40             int id=i&(-2);
 41             int v=e[id].u;
 42             if(!vis[v]&&e[id].cap>e[id].flow){
 43                 vis[v]=1;
 44                 d[v]=d[u]+1;
 45                 q.push(v);
 46             }
 47         }
 48     }
 49 }
 50 int augment(){
 51     int u=t,a=inf;
 52     while(u!=s){
 53         int id=p[u];
 54         a=min(a,e[id].cap-e[id].flow);
 55         u=e[id].u;
 56     }
 57     u=t;
 58     while(u!=s){
 59         int id=p[u];
 60         e[id].flow+=a;
 61         e[id^1].flow-=a;
 62         u=e[id].u;
 63     }
 64     return a;
 65 }
 66 int ISAP(){
 67     bfs();
 68     CLR(num,0);
 69     for(int i=0;i<N;i++){
 70         cur[i]=head[i];
 71         if(~d[i]) num[d[i]]++;
 72     }
 73     int flow=0;
 74     int u=s;
 75     while(d[s]<N){
 76         if(u==t){
 77             flow+=augment();
 78             u=s;
 79         }
 80         int ok=0;
 81         for(int i=cur[u];~i;i=e[i].nex){
 82             int v=e[i].v;
 83             if(d[u]==d[v]+1&&e[i].cap>e[i].flow){
 84                 ok=1;
 85                 p[v]=i;
 86                 cur[u]=i;
 87                 u=v;
 88                 break;
 89             }
 90         }
 91         if(!ok){
 92             int m=N-1;
 93             for(int i=head[u];~i;i=e[i].nex){
 94                 if(e[i].cap>e[i].flow&&~d[e[i].v]) m=min(m,d[e[i].v]);
 95             }
 96             if(--num[d[u]]==0) break;
 97             num[d[u]=m+1]++;
 98             cur[u]=head[u];
 99             if(u!=s) u=e[p[u]].u;
100         }
101     }
102     return flow;
103 }
104 int val[maxv];
105 int main(){
106     int n,m;
107     while(scanf("%d%d",&n,&m)!=EOF){
108         init();
109         int x;
110         CLR(val,0);
111         for(int i=1;i<=n;i++){
112             int temp=0;
113             for(int j=1;j<=m;j++){
114                 scanf("%d",&x);
115                 temp=(temp<<1)+x;
116             }
117             val[temp]++;
118         }
119         int bc=(1<<m)-1;
120         s=0;t=bc+m+1;
121         N=t+1;
122         for(int i=1;i<=m;i++){
123             scanf("%d",&x);
124             add(bc+i,t,x);
125         }
126         if(val[0]) {
127             puts("NO");
128             continue;
129         }
130         for(int i=1;i<=bc;i++)if(val[i]){
131             add(s,i,val[i]);
132              for(int j=1;j<=m;j++) if(i>>(m-j)&1){  //位运算又出了差错=_=|| 
133                 add(i,bc+j,inf);
134             }
135         }
136         int flow=ISAP();
137         if(flow==n) puts("YES");
138         else puts("NO");
139     }
140     return 0;
141 }
View Code

 

posted @ 2017-07-24 21:49  yijiull  阅读(178)  评论(0编辑  收藏  举报