【系列】网络流

bzoj 1934 善意的投票

题目大意:

每个人可以选择睡不睡午觉 给出他们原本的意愿 以及m对朋友表示他们之间应当选择相同 求好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数

思路:

每个意愿不同的人分别连向源和汇 对于一对朋友之间连边 这样最小割即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<vector>
 8 #include<queue>
 9 #include<complex>
10 #include<map>
11 #define rep(i,s,t) for(register int i=(s);i<=(t);++i)
12 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i)
13 #define ren for(register int i=fst[x];i;i=nxt[i])
14 #define Fill(x,t) memset(x,t,sizeof(x))
15 #define ll long long
16 #define Cd complex<double>
17 #define inf 2139062143
18 #define MOD 998244353
19 #define MAXN 310
20 #define MAXM 90100
21 using namespace std;
22 inline int read()
23 {
24     int x=0,f=1;char ch=getchar();
25     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
26     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 int n,m,S,T;
30 struct Dinic
31 {
32     int fst[MAXN],cur[MAXN],nxt[MAXM<<1],to[MAXM<<1],val[MAXM<<1];
33     int vis[MAXN],dep[MAXN],tot,cnt,q[MAXN],l,r;
34     void mem(){memset(fst,0,sizeof(fst));cnt=1;}
35     void add(int u,int v,int w){nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
36     void ins(int u,int v,int w){add(u,v,w);add(v,u,0);}
37     int bfs()
38     {
39         q[l=r=1]=T,vis[T]=++tot,dep[T]=0;int x;
40         while(l<=r)
41         {
42              x=q[l++];
43              ren if(val[i^1]&&vis[to[i]]!=tot) {vis[to[i]]=tot,dep[to[i]]=dep[x]+1,q[++r]=to[i];if(to[i]==S)return 1;}
44         }
45         return vis[S]==tot;
46     }
47     int dfs(int x,int now)
48     {
49         if(x==T||!now) return now;
50         int flow=0,f;
51         for(int& i=cur[x];i;i=nxt[i])
52             if(val[i]&&dep[to[i]]==dep[x]-1&&(f=dfs(to[i],min(now,val[i]))))
53                 {now-=f,flow+=f,val[i]-=f,val[i^1]+=f;if(!now) break;}
54         return flow;
55     }
56     int solve()
57     {
58         int ans=0,f;
59         while(bfs()) {memcpy(cur,fst,sizeof(cur));while(f=dfs(S,inf)) ans+=f;}
60         return ans;
61     }
62 }D;
63 int main()
64 {
65     n=read(),m=read(),S=0,T=n+1;D.mem();int a,b;rep(i,1,n) {a=read();if(a) D.ins(S,i,1);else D.ins(i,T,1);}
66     rep(i,1,m) a=read(),b=read(),D.ins(a,b,1),D.ins(b,a,1);
67     printf("%d\n",D.solve());
68 }
View Code

 

bzoj 1066 蜥蜴

题目大意:

一个网格图,一开始有一些蜥蜴,一些网格上有石柱,每个石柱在被一个蜥蜴离开之后高度会减一 ,减为0后就不能被跳了

每只蜥蜴只能从一个石柱跳到不超过d的距离的石柱上去 求最少不能出去的蜥蜴数量

思路:

对于每个石柱拆成两个点 中间连一条边来满足这个石柱的限制

其余的就从每个石柱的第二个点连向可以跳到石柱的第一个点 最后用总数-最大流即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<vector>
 8 #include<queue>
 9 #include<complex>
10 #include<map>
11 #define rep(i,s,t) for(register int i=(s);i<=(t);++i)
12 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i)
13 #define ren for(register int i=fst[x];i;i=nxt[i])
14 #define Fill(x,t) memset(x,t,sizeof(x))
15 #define ll long long
16 #define Cd complex<double>
17 #define inf 2139062143
18 #define MOD 998244353
19 #define MAXN 510
20 #define MAXM 320100
21 using namespace std;
22 inline int read()
23 {
24     int x=0,f=1;char ch=getchar();
25     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
26     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 int n,m,d,S,T,all;
30 struct Dinic
31 {
32     int fst[MAXN],cur[MAXN],nxt[MAXM<<1],to[MAXM<<1],val[MAXM<<1];
33     int vis[MAXN],dep[MAXN],tot,cnt,q[MAXN],l,r;
34     void mem(){memset(fst,0,sizeof(fst));cnt=1;}
35     void add(int u,int v,int w){nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
36     void ins(int u,int v,int w){add(u,v,w);add(v,u,0);}
37     int bfs()
38     {
39         q[l=r=1]=T,vis[T]=++tot,dep[T]=0;int x;
40         while(l<=r)
41         {
42              x=q[l++];
43              ren if(val[i^1]&&vis[to[i]]!=tot) {vis[to[i]]=tot,dep[to[i]]=dep[x]+1,q[++r]=to[i];if(to[i]==S)return 1;}
44         }
45         return vis[S]==tot;
46     }
47     int dfs(int x,int now)
48     {
49         if(x==T||!now) return now;
50         int flow=0,f;
51         for(int& i=cur[x];i;i=nxt[i])
52             if(val[i]&&dep[to[i]]==dep[x]-1&&(f=dfs(to[i],min(now,val[i]))))
53                 {now-=f,flow+=f,val[i]-=f,val[i^1]+=f;if(!now) break;}
54         return flow;
55     }
56     int solve()
57     {
58         int ans=0,f;
59         while(bfs()) {memcpy(cur,fst,sizeof(cur));while(f=dfs(S,inf)) ans+=f;}
60         return ans;
61     }
62 }D;
63 char mp[25][25],ch[25];
64 int cur[25][25];
65 void srch(int x,int y)
66 {
67     if(mp[x][y]=='0') return ;
68     if((x-d<1||x+d>n||y-d<1||y+d>m)) D.ins(cur[x][y]+1,T,inf);
69     rep(i,x-d,x+d) if(i<1||i>n) continue;
70     else rep(j,y-d,y+d) if(j<1||j>m) continue;
71     else if(abs(x-i)+abs(y-j)<=d) D.ins(cur[x][y]+1,cur[i][j],inf);
72 }
73 int main()
74 {
75     n=read(),m=read(),d=read(),S=0,T=(n*m+2)<<1,all=1;int num=0;D.mem();
76     rep(i,1,n) {scanf("%s",mp[i]+1);rep(j,1,m) {if(mp[i][j]!='0') D.ins(all,all+1,mp[i][j]-'0');cur[i][j]=all,all+=2;}}
77     rep(i,1,n) {scanf("%s",ch+1);rep(j,1,m) {srch(i,j);if(ch[j]=='L') D.ins(S,cur[i][j],1),num++;}}
78     printf("%d",num-D.solve());
79 }
View Code

 

bzoj 4625 水晶

题目大意:

地图由密铺的六边形单元组成,每个单元与其他
六个单元相邻。为了方便起见,我们用坐标(x,y,z)描述一个单元的位置,表示从原点开始按如图所示的x,y,z方向
各走若干步之后到达的地方。有可能有两个坐标描述同一个单元,比如(1,1,1)和(0,0,0)描述的都是原点
显然(x,y,z)单元和(x+1, y,z),(x-1,y,z),(x,y+1,z),(x,y-1,z),(x, y, z+1),(x,y, z-1)相邻。有N块水晶
位于地图的单元内,第i块水晶位于坐标(xi, yi, zi)所表示的单元中,并拥有ci的价值。每个单元内部可能会有
多块水晶。地图中,有一些单元安装有能量源。如下图,任何满足x+y+z是3的整数倍的坐标所描述的单元内都安装
有能量源。
 
有能量源的单元中的水晶价值将会额外增加10%.如果三块水晶所在的单元满足特定排列,那么它们将会引发共振。
共振分两种,a共振和b共振。a共振:如果三块水晶所在的单元两两相邻地排成一个三角形,那么会引起a共振。
图中每一个三角形表示这三个单元各有一块水晶将会发生一个a共振。b共振:如果三块水晶所在的单元依次相邻地
排成一条长度为2的直线段,且正中间的单元恰好有能量源,那么会引起b共振。
 
图中粉红色线段表示这三个单元各有一块水晶将会发生一个b共振,黑色线段表示即使这三个单元有水晶也不会发
生b共振。现在你要炸掉一部分水晶,使得任何共振都不会发生的前提下,剩余水晶的价值总和最大

思路:

首先根据题意发现题为一个三分图 由于b共振的条件 

因此把坐标和%3位0的放在中间 剩下两个顺序随意 通过拆点来满足价值 用总数-最小割即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<vector>
 8 #include<queue>
 9 #include<complex>
10 #include<map>
11 #define rep(i,s,t) for(register int i=(s);i<=(t);++i)
12 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i)
13 #define ren for(register int i=fst[x];i;i=nxt[i])
14 #define Fill(x,t) memset(x,t,sizeof(x))
15 #define ll long long
16 #define Cd complex<double>
17 #define inf 2139062143
18 #define MOD 998244353
19 #define MAXN 100100
20 #define MAXM 400100
21 using namespace std;
22 inline int read()
23 {
24     int x=0,f=1;char ch=getchar();
25     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
26     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 int n,m,S,T,x[MAXN],y[MAXN],z[MAXN];
30 double all,d[MAXN];
31 int calc(int x,int y) {return 4000*(x+2000)+y+6000;}
32 map <int,int> hsh;
33 struct Dinic
34 {
35     int fst[MAXN],cur[MAXN],nxt[MAXM<<1],to[MAXM<<1];double val[MAXM<<1];
36     int vis[MAXN],dep[MAXN],tot,cnt,q[MAXN],l,r;
37     void mem(){memset(fst,0,sizeof(fst));cnt=1;}
38     void add(int u,int v,double w){nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
39     void ins(int u,int v,double w){add(u,v,w);add(v,u,0.0);}
40     int bfs()
41     {
42         q[l=r=1]=T,vis[T]=++tot,dep[T]=0;int x;
43         while(l<=r)
44         {
45              x=q[l++];
46              ren if(val[i^1]>0.0&&vis[to[i]]!=tot) {vis[to[i]]=tot,dep[to[i]]=dep[x]+1,q[++r]=to[i];if(to[i]==S)return 1;}
47         }
48         return vis[S]==tot;
49     }
50     double dfs(int x,double now)
51     {
52         if(x==T||now==0.0) return now;
53         double flow=0,f;
54         for(int& i=cur[x];i;i=nxt[i])
55             if(val[i]>0.0&&dep[to[i]]==dep[x]-1&&((f=dfs(to[i],min(now,val[i])))!=0.0))
56                 {now-=f,flow+=f,val[i]-=f,val[i^1]+=f;if(!now) break;}
57         return flow;
58     }
59     double solve()
60     {
61         double ans=0,f;
62         while(bfs()) {memcpy(cur,fst,sizeof(cur));while((f=dfs(S,inf))!=0.0) ans+=f;}
63         return ans;
64     }
65 }D;
66 int main()
67 {
68     n=read(),S=(n+3)<<1,T=((n+3)<<1|1);D.mem();int tmp,to;rep(i,1,n)
69     {
70         x[i]=read(),y[i]=read(),z[i]=read(),d[i]=read();
71         if((x[i]+y[i]+z[i])%3==0) d[i]*=1.1;all+=d[i];
72         tmp=hsh[to=calc(x[i]-=z[i],y[i]-=z[i])];
73         if(!tmp) hsh[to]=tmp=i;D.ins(tmp<<1,tmp<<1|1,d[i]);
74     }
75     rep(i,1,n)
76     {
77         tmp=hsh[to=calc(x[i],y[i])];if(tmp!=i) continue;
78         if((x[i]+y[i]+33333)%3==1) D.ins(i<<1|1,T,inf);
79         else 
80         {
81             if((x[i]+y[i]+33333)%3==2) D.ins(S,i<<1,inf);
82             D.ins(i<<1|1,hsh[calc(x[i],y[i]+1)]<<1,inf);
83             D.ins(i<<1|1,hsh[calc(x[i]+1,y[i])]<<1,inf);
84             D.ins(i<<1|1,hsh[calc(x[i]-1,y[i]-1)]<<1,inf);
85         }
86     }
87     printf("%.1lf\n",all-D.solve());
88 }
View Code

 

bzoj 1391 order

题目大意:

n个任务 m个机器 每个任务都需要一些机器 一个机器可以租借或购买 具有不同的价格

每个机器对不同的任务租借费用不同 任务的利润和机器的购买价格相等

思路:

若不考虑租借 则为最大权闭合子图 考虑修改这个图 对于原来流量为inf的边修改为相应的租借费用

这样对于一条$S\rightarrow T$的路径,总会有一条边被割掉,即为买机器或租借某一个机器或者不要这个收益

用总收益减去最小割即为答案

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<vector>
 8 #include<queue>
 9 #include<complex>
10 #include<map>
11 #define rep(i,s,t) for(register int i=(s);i<=(t);++i)
12 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i)
13 #define ren for(register int i=fst[x];i;i=nxt[i])
14 #define Fill(x,t) memset(x,t,sizeof(x))
15 #define ll long long
16 #define Cd complex<double>
17 #define inf 2139062143
18 #define MOD 998244353
19 #define MAXN 2510
20 #define MAXM 1500100
21 using namespace std;
22 inline int read()
23 {
24     int x=0,f=1;char ch=getchar();
25     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
26     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 int n,m,S,T,all;
30 struct Dinic
31 {
32     int fst[MAXN],cur[MAXN],nxt[MAXM<<1],to[MAXM<<1],val[MAXM<<1];
33     int vis[MAXN],dep[MAXN],tot,cnt,q[MAXN],l,r;
34     void mem(){memset(fst,0,sizeof(fst));cnt=1;}
35     void add(int u,int v,int w){nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
36     void ins(int u,int v,int w){add(u,v,w);add(v,u,0);}
37     int bfs()
38     {
39         q[l=r=1]=T,vis[T]=++tot,dep[T]=0;int x;
40         while(l<=r)
41         {
42              x=q[l++];
43              ren if(val[i^1]&&vis[to[i]]!=tot){vis[to[i]]=tot,dep[to[i]]=dep[x]+1,q[++r]=to[i];if(to[i]==S)return 1;}
44         }
45         return vis[S]==tot;
46     }
47     int dfs(int x,int now)
48     {
49         if(x==T||!now) return now;int flow=0,f;
50         for(int& i=cur[x];i;i=nxt[i])
51             if(val[i]&&dep[to[i]]==dep[x]-1&&(f=dfs(to[i],min(now,val[i]))))
52                 {now-=f,flow+=f,val[i]-=f,val[i^1]+=f;if(!now) break;}
53         return flow;
54     }
55     int solve()
56     {
57         int ans=0,f;
58         while(bfs()) {memcpy(cur,fst,sizeof(cur));while(f=dfs(S,inf)) ans+=f;}
59         return ans;
60     }
61 }D;
62 int main()
63 {
64     n=read(),m=read(),S=n+m+5,T=S+1;D.mem();int a,b,c;rep(i,1,n) 
65     {
66         a=read(),all+=a;D.ins(S,i,a);a=read();rep(j,1,a)
67             b=read(),c=read(),D.ins(i,b+n,c);
68     }
69     rep(i,1,m) a=read(),D.ins(i+n,T,a);
70     printf("%d\n",all-D.solve());
71 }
View Code

 

bzoj 1070 修车

题目大意:

m个人修n辆车,不同的人修不同的车需要不同的时间,求所有人最短修完车的时间(包含等待时间)

思路:

把每个人拆成n个点,表示第$i$个倒数第$j$个修哪辆车

这样倒数第$j$个的影响就是$j$倍的影响(会影响加上自己的$j$个人的等待时间)

 1 // luogu-judger-enable-o2
 2 // luogu-judger-enable-o2
 3 #include<iostream>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<cstring>
 8 #include<algorithm>
 9 #include<vector>
10 #include<queue>
11 #include<map>
12 #include<set>
13 #include<complex>
14 #include<iomanip>
15 #define Fill(a,x) memset(a,x,sizeof(a))
16 #define rep(i,s,t) for(register int i=(s),i__end=(t);i<=i__end;++i)
17 #define dwn(i,s,t) for(register int i=(s),i__end=(t);i>=i__end;--i)
18 #define ren for(int i=fst[x];i;i=nxt[i])
19 #define inf 2139062143
20 #define ll long long
21 #define ull unsigned long long
22 #define MAXN 710
23 #define MAXM 40010
24 #define MOD 998244353 
25 using namespace std;
26 inline int read()
27 {
28     int x=0,f=1;char ch=getchar();
29     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
30     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
31     return x*f;
32 }
33 int S,T,n,m,g[70][70];
34 struct zkw
35 {
36     int fst[MAXN],nxt[MAXM<<1],to[MAXM<<1],cst[MAXM<<1],val[MAXM<<1],cnt;
37     int q[MAXN<<4],hd,tl,vis[MAXN],tot,dis[MAXN];ll ans;
38     zkw(){Fill(fst,0);cnt=1,ans=0LL;}
39     void add(int u,int v,int w,int c) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,cst[cnt]=c,val[cnt]=w;}
40     void ins(int u,int v,int w,int c) {add(u,v,w,c);add(v,u,0,-c);}
41     int spfa()
42     {
43         Fill(vis,0);Fill(dis,127);q[hd=tl=1]=T,dis[T]=0;int x;
44         while(hd<=tl)
45         {
46             x=q[hd++],vis[x]=0;
47             ren if(val[i^1]&&dis[to[i]]>dis[x]-cst[i]) 
48                 {dis[to[i]]=dis[x]-cst[i];if(!vis[to[i]]) vis[to[i]]=1,q[++tl]=to[i];}
49         }
50         return dis[S]!=inf;
51     }
52     int dfs(int x,int a)
53     {
54         if(x==T||!a) {ans+=dis[S]*a;return a;}
55         if(vis[x]) return 0;vis[x]=1;int f,flw=0;
56         ren if(val[i]&&dis[to[i]]==dis[x]-cst[i]&&(f=dfs(to[i],min(a,val[i]))))
57             {flw+=f,val[i]-=f,val[i^1]+=f,a-=f;if(!a) break;}
58         return flw;
59     }
60     int solve(int res=0)
61     {
62         while(spfa()) res+=dfs(S,inf);return res;
63     }
64 }Z;
65 int main()
66 {
67     n=read(),m=read();S=n*m+m+1,T=S+1;rep(i,1,n*m) Z.ins(S,i,1,0);
68     rep(i,1,m) Z.ins(i+n*m,T,1,0);rep(i,1,m) rep(j,1,n) g[i][j]=read();
69     rep(i,1,n) rep(j,1,m) rep(k,1,m) Z.ins((i-1)*m+j,n*m+k,1,j*g[k][i]);
70     Z.solve();printf("%.2lf\n",1.0*Z.ans/m);
71 }
View Code

 

bzoj 3894 文理分科

题目大意:

每个人可以选文理科分别得到两种价值$a$或$b$

若这个人的四连块中的人选课都与他一样则会得到附加的$c$或$d$

思路:

每个人拆成三个点 第一个点表示自己 分别与源汇点连边表示选文或理

第二个点连向包括自己和相邻的五个点的第一个点 容量为inf(因为不能被割) 从源向该点连边容量为附加的文科值

第三个点与第二个点类似表示理科

这样的话使用总代价-最小割即为答案

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #define ll long long
12 #define inf 2139062143
13 #define MAXN 30500
14 #define MAXM 300100
15 #define MOD 998244353
16 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
17 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
18 #define ren for(register int i=fst[x];i;i=nxt[i])
19 #define pb(i,x) vec[i].push_back(x)
20 #define pls(a,b) (a+b)%MOD
21 #define mns(a,b) (a-b+MOD)%MOD
22 #define mul(a,b) (1LL*(a)*(b))%MOD
23 using namespace std;
24 inline int read()
25 {
26     int x=0,f=1;char ch=getchar();
27     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
28     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
29     return x*f;
30 }
31 int n,m,S,T,sum,dx[5]={1,-1,0,0,0},dy[5]={0,0,1,-1,0};
32 struct Dinic
33 {
34     int fst[MAXN],nxt[MAXM<<1],to[MAXM<<1],val[MAXM<<1],cnt;
35     int q[MAXN],l,r,vis[MAXN],dep[MAXN],cur[MAXN],tot;
36     Dinic(){memset(fst,0,sizeof(fst));memset(vis,0,sizeof(vis));cnt=1,tot=0;}
37     void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
38     void ins(int u,int v,int w) {add(u,v,w);add(v,u,0);}
39     int bfs()
40     {
41         vis[T]=++tot,q[l=r=1]=T,dep[T]=0;int x;
42         while(l<=r)
43         {
44             x=q[l++];ren if(vis[to[i]]!=tot&&val[i^1])
45                 vis[to[i]]=tot,dep[to[i]]=dep[x]+1,q[++r]=to[i];
46         }
47         return vis[S]==tot;
48     }
49     int dfs(int x,int a)
50     {
51         if(x==T||!a) return a;int flw=0,f;
52         for(int& i=cur[x];i&&a;i=nxt[i])
53             if(val[i]&&dep[to[i]]==dep[x]-1&&(f=dfs(to[i],min(a,val[i]))))
54                 flw+=f,a-=f,val[i]-=f,val[i^1]+=f;
55         return flw;
56     }
57     int solve()
58     {
59         int ans=0,f;
60         while(bfs()){memcpy(cur,fst,sizeof(cur));while(f=dfs(S,inf)) ans+=f;}
61         return ans;
62     }
63 }D;
64 int ok(int x,int y) {return x>=0&&x<=n&&y>=0&&y<=m;}
65 int calc(int k,int x,int y) {return k*(n+1)*(m+1)+x*(m+1)+y;}
66 int main()
67 {
68     n=read()-1,m=read()-1,S=3*(n+1)*(m+1)+1,T=S+1;int x,nx,ny;
69     rep(i,0,n) rep(j,0,m) {x=read(),sum+=x;D.ins(S,calc(0,i,j),x);}
70     rep(i,0,n) rep(j,0,m) {x=read(),sum+=x;D.ins(calc(0,i,j),T,x);}
71     rep(i,0,n) rep(j,0,m)
72     {
73         x=read(),sum+=x;rep(k,0,4) if(ok(nx=(i+dx[k]),(ny=j+dy[k])))
74             D.ins(calc(1,i,j),calc(0,nx,ny),inf);
75         D.ins(S,calc(1,i,j),x);
76     }
77     rep(i,0,n) rep(j,0,m)
78     {
79         x=read(),sum+=x;rep(k,0,4) if(ok(nx=(i+dx[k]),(ny=j+dy[k])))
80             D.ins(calc(0,nx,ny),calc(2,i,j),inf);
81         D.ins(calc(2,i,j),T,x);
82     }
83     printf("%d\n",sum-D.solve());
84 }
View Code

 

bzoj 1143 祭祀

题目大意:

求DAG的最长反链(一个点集使其两两不可达

思路:

最长反链=最小链覆盖

求最小链覆盖需要把每个点拆成两个,每个能到达的点对,由左边的$u$连向右边的$v$ ,求最大点独立集

最大点独立集=$n$-最大匹配

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #define ll long long
12 #define db double
13 #define inf 2139062143
14 #define MAXN 510
15 #define MAXM 100300
16 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
17 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
18 #define ren for(register int i=fst[x];i;i=nxt[i])
19 #define pb(i,x) vec[i].push_back(x)
20 #define pls(a,b) (a+b)%MOD
21 #define mns(a,b) (a-b+MOD)%MOD
22 #define mul(a,b) (1LL*(a)*(b))%MOD
23 using namespace std;
24 inline int read()
25 {
26     int x=0,f=1;char ch=getchar();
27     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
28     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
29     return x*f;
30 }
31 int n,m,S,T,mp[110][110];
32 struct Dinic
33 {
34     int fst[MAXN],nxt[MAXM<<1],to[MAXM<<1],val[MAXM<<1],cnt,cur[MAXN];
35     int vis[MAXN],dis[MAXN],tot,q[MAXN],l,r;
36     Dinic(){memset(fst,0,sizeof(fst));cnt=1;}
37     void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
38     void ins(int u,int v,int w) {add(u,v,w);add(v,u,0);}
39     int bfs()
40     {
41         q[l=r=1]=T,vis[T]=++tot,dis[T]=0;int x;
42         while(l<=r)
43         {
44             x=q[l++];ren if(vis[to[i]]!=tot&&val[i^1]) 
45                 dis[to[i]]=dis[x]+1,vis[to[i]]=tot,q[++r]=to[i];
46         }
47         return vis[S]==tot;
48     }
49     int dfs(int x,int a)
50     {
51         if(x==T||!a) return a;int flw=0,f;
52         for(int& i=cur[x];i&&a;i=nxt[i]) 
53             if(dis[to[i]]==dis[x]-1&&val[i]&&(f=dfs(to[i],min(a,val[i]))))
54                 a-=f,flw+=f,val[i]-=f,val[i^1]+=f;
55         return flw;
56     }
57     int solve(int res=0)
58     {
59         int f;while(bfs())
60             {rep(i,1,T) cur[i]=fst[i];while(f=dfs(S,inf)) res+=f;}
61         return res;
62     }
63 }D;
64 int main()
65 {
66     n=read(),m=read();int a,b;S=n<<1|1,T=S+1;
67     while(m--) a=read(),b=read(),mp[a][b]=1;
68     rep(k,1,n) rep(i,1,n) rep(j,1,n) mp[i][j]|=(mp[i][k]&mp[k][j]);
69     rep(i,1,n) rep(j,1,n) if(mp[i][j]) D.ins(i,j+n,1);
70     rep(i,1,n) D.ins(S,i,1),D.ins(i+n,T,1);
71     printf("%d\n",n-D.solve());
72 }
View Code

 

posted @ 2018-12-14 11:24  jack_yyc  阅读(172)  评论(0编辑  收藏  举报