前述:这周周一做了两个组合数专题的题,依旧是容斥定理的题目,然后就不会了,正好专题延时了,就转向看了看网络流的博客,a了几道最大流的题,有简单的,有比较综合的,也只能不断摸索着前进,简单的构图还是可以想出来的,但是还是没理解拆点的意义所在,就是想不到为什么要拆点,也做了一些简单的尝试,就是把题解上拆点的做法,用不拆点的方法做,可是想法总觉得很好,就是总是wr,看起来我需要用脑子运行一下这个程序,才能知道拆点的真正作用。
题目大意:就是求1到m的最大流,裸的最大流的题目,借着连连模板。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#define maxn 20
#define INF 1e9
using namespace std;
struct edge{
edge(){};
edge(int from,int to,int val,int flow):from(from),to(to),val(val),flow(flow){}
int from,to,val,flow;
};
int n,m;
vector<edge>p;
vector<int>num[maxn];
bool visit[maxn];
int dis[maxn];
int cur[maxn];
void add(int x,int y,int z){
p.push_back(edge(x,y,z,0));
p.push_back(edge(y,x,0,0));
int xx=p.size();
num[x].push_back(xx-2);
num[y].push_back(xx-1);
}
bool bfs(int s,int t){
int i,j;
memset (visit,0,sizeof(visit));
queue<int>qq;
qq.push(s);
dis[s]=0;
visit[s]=1;
while (!qq.empty()){
int u=qq.front();
qq.pop();
for (i=0;i<num[u].size();i++){
edge& e=p[num[u][i]];
if (!visit[e.to]&&e.val>e.flow){
visit[e.to]=1;
dis[e.to]=dis[u]+1;
qq.push(e.to);
}
}
}
return visit[t];
}
int dfs(int x,int t,int val){
if (x==t||val==0){
return val;
}
int flow=0,f;
for (int& i=cur[x];i<num[x].size();i++){
edge& e=p[num[x][i]];
if (dis[x]+1==dis[e.to]&&(f=dfs(e.to,t,min(val,e.val-e.flow)))>0){
e.flow+=f;
p[num[x][i]^1].flow-=f;
flow+=f;
val-=f;
if (val==0)break;
}
}
return flow;
}
int dinic(int s,int t){
int flow=0;
while (bfs(s,t)){
memset (cur,0,sizeof(cur));
flow+=dfs(s,t,INF);
}
return flow;
}
int main(){
int i,j,k,l,x,y,z,t;
while (scanf("%d%d",&m,&n)!=EOF){
p.clear();
for (i=1;i<=n;i++)num[i].clear();
for (i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
printf("%d\n",dinic(1,n));
}
}