Description
Input
Output
Sample Input
5 4 1 2 40 1 4 20 2 4 20 2 3 30 3 4 10
Sample Output
50
这题比D题还容易,最大流水题……不过是很经典的题目,没有什么转化,全裸的最大流。
1.EK算法:有点像Dinic算法,因为这个是从Dinic算法中来的,把分层去掉了而已,所以代码在DFS中还是有点像的,正向边减和反向边加。
1是源点,m是汇点,直接用EK算法0ms过……因为怕结果超出int,所以结果用了long long 型。
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <list> #include <queue> #include <string> #include <cstring> #include <map> #include <set> #define PI acos(-1.0) #define mem(a,b) memset(a,b,sizeof(a)) #define sca(a) scanf("%d",&a) #define pri(a) printf("%d\n",a) #define MM 10002 #define MN 205 #define INF 168430090 using namespace std; typedef long long ll; int n,m,k,t,pre[MN],vis[MN],Map[MN][MN]; ll ans; int bfs() { mem(vis,0); queue<int>q; q.push(1); vis[1]=1; while(!q.empty()) //找增广路 { int u=q.front(); q.pop(); for(int v=1;v<=m;v++) { if(!vis[v]&&Map[u][v]) { pre[v]=u; //记录前向结点 if(v==m) return 1; q.push(v); vis[v] = 1; } } } return 0; } void change() { int i,sum=INF; for(i=m; i != 1; i = pre[i]) sum = min(sum,Map[pre[i]][i]); for(i=m; i != 1; i = pre[i]) { Map[pre[i]][i]-=sum; //正向边减 Map[i][pre[i]]+=sum; //反向边加 } ans+=sum; } int main() { while(~scanf("%d%d",&n,&m)) { mem(Map,0); ans=0; int u,v,w,i; while(n--) { scanf("%d%d%d",&u,&v,&w); Map[u][v]+=w; } while(bfs()) change(); pri(ans); } return 0; }
2.Dinic算法:
学习此算法的博客网址:http://www.cnblogs.com/acSzz/archive/2012/09/13/2683820.html
在图论书中也有说明此算法的。简单来说就是分层,从源点开始从0一层一层往后推,然后大于汇点的层(包括点与边)在DFS中就没有用到了,就相当于把这些点与边去掉了,这样当然效率更高啦!!!这就是EK算法中不相同的地方,EK是Dinic简化而来的,但是效率不如Dinic好,因为未分层,所以查询了不必要的边与结点。
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <list> #include <queue> #include <string> #include <cstring> #include <map> #include <set> #define PI acos(-1.0) #define mem(a,b) memset(a,b,sizeof(a)) #define sca(a) scanf("%d",&a) #define pri(a) printf("%d\n",a) #define MM 10002 #define MN 205 #define INF 168430090 using namespace std; typedef long long ll; int n,m,d[MN],Map[MN][MN]; ll ans; int bfs() { mem(d,-1); queue<int>q; q.push(1); d[1]=0; while(!q.empty()) //找增广路 { int u=q.front(); q.pop(); for(int v=1;v<=m;v++) { if(d[v]==-1&&Map[u][v]) { d[v]=d[u]+1; //分层,越往后,层数越大 q.push(v); } } } return d[m]!=-1; } int dfs(int u,int Min) { int sum; if(u==m) return Min; for(int v=1;v<=m;v++) if(Map[u][v]&&d[v]==d[u]+1&&(sum=dfs(v,min(Min,Map[u][v])))) { Map[u][v]-=sum; Map[v][u]+=sum; return sum; } return 0; } void Dinic() { int tmp; while(bfs()) { while(tmp=dfs(1,INF)) ans+=tmp; } pri(ans); } int main() { while(~scanf("%d%d",&n,&m)) { mem(Map,0); ans=0; int u,v,w; while(n--) { scanf("%d%d%d",&u,&v,&w); Map[u][v]+=w; } Dinic(); } return 0; }