码迷,mamicode.com
首页 > 其他好文 > 详细

网络流小结

时间:2015-09-15 17:55:10      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:

1.hdu1532

最基础最大流,给出起点,终点,和一些边,求最大流

技术分享
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int inf = 1000000000;
const int maxn = 20000, maxm = 500000;
struct Edge{
    int v, f, nxt;
};
int src, sink;
int g[maxn+10];
int nume;
Edge e[maxm * 2 +10];
void addedge(int u, int v, int c){
    e[++nume].v = v;
    e[nume].f = c;
    e[nume].nxt = g[u];
    g[u] = nume;
    e[++nume].v = u;
    e[nume].f = 0;
    e[nume].nxt = g[v];
    g[v] = nume;
}
void init(){
    memset(g, 0, sizeof(g));
    nume = 1;
}
queue<int> que;
bool vis[maxn+10];
int dist[maxn + 10];
void bfs(){
    memset(dist, 0, sizeof(dist));
    while(!que.empty()) que.pop();
    vis[src] = true;
    que.push(src);
    while(!que.empty()){
        int u = que.front();
        que.pop();
        for(int i = g[u]; i; i = e[i].nxt)
        if(e[i].f && !vis[e[i].v]){
            que.push(e[i].v);
            dist[e[i].v] = dist[u] + 1;
            vis[e[i].v] = true;
        }
    }
}
int dfs(int u, int delta){
    if(u == sink){
        return delta;
    }else{
        int ret = 0;
        for(int i = g[u]; delta && i; i = e[i].nxt)
        if(e[i].f && dist[e[i].v] == dist[u]+1){
            int dd = dfs(e[i].v, min(e[i].f, delta));
            e[i].f -= dd;
            e[i^1].f += dd;
            delta -= dd;
            ret += dd;
        }
        return ret;
    }
}
int maxflow(){
    int ret = 0;
    while(true){
        memset(vis, 0, sizeof(vis));
        bfs();
        if(!vis[sink]) return ret;
        ret += dfs(src, inf);
    }
}
int main(){
    int n, m;
    while(scanf("%d%d", &m, &n)!=EOF){
        init();
        for(int i = 0;i < m; i++){
            int u, v, l;
            scanf("%d%d%d", &u, &v, &l);
            addedge(u, v, l);
        }
        src = 1;
        sink = n;
        printf("%d\n", maxflow());
    }
}
View Code

 

2.hdu3549

最基础最大流,套模板就行

技术分享
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int inf = 1000000000;
const int maxn = 20000, maxm = 500000;
struct Edge{
    int v, f, nxt;
};
int src, sink;
int g[maxn+10];
int nume;
Edge e[maxm * 2 +10];
void addedge(int u, int v, int c){
    e[++nume].v = v;
    e[nume].f = c;
    e[nume].nxt = g[u];
    g[u] = nume;
    e[++nume].v = u;
    e[nume].f = 0;
    e[nume].nxt = g[v];
    g[v] = nume;
}
void init(){
    memset(g, 0, sizeof(g));
    nume = 1;
}
queue<int> que;
bool vis[maxn+10];
int dist[maxn + 10];
void bfs(){
    memset(dist, 0, sizeof(dist));
    while(!que.empty()) que.pop();
    vis[src] = true;
    que.push(src);
    while(!que.empty()){
        int u = que.front();
        que.pop();
        for(int i = g[u]; i; i = e[i].nxt)
        if(e[i].f && !vis[e[i].v]){
            que.push(e[i].v);
            dist[e[i].v] = dist[u] + 1;
            vis[e[i].v] = true;
        }
    }
}
int dfs(int u, int delta){
    if(u == sink){
        return delta;
    }else{
        int ret = 0;
        for(int i = g[u]; delta && i; i = e[i].nxt)
        if(e[i].f && dist[e[i].v] == dist[u]+1){
            int dd = dfs(e[i].v, min(e[i].f, delta));
            e[i].f -= dd;
            e[i^1].f += dd;
            delta -= dd;
            ret += dd;
        }
        return ret;
    }
}
int maxflow(){
    int ret = 0;
    while(true){
        memset(vis, 0, sizeof(vis));
        bfs();
        if(!vis[sink]) return ret;
        ret += dfs(src, inf);
    }
}
int main(){
    int cas = 1;
    int n, m;
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d%d", &n, &m);
        init();
        for(int i = 0;i < m; i++){
            int u, v, l;
            scanf("%d%d%d", &u, &v, &l);
            addedge(u, v, l);
        }
        src = 1;
        sink = n;
        printf("Case %d: %d\n", cas++, maxflow());
    }
}
View Code

 

3.hdu3572

题意:有M个机器,有N个任务。每个任务必须在Si 或者以后开始做,在Ei 或者之前完成,完成任务必须处理Pi 个时间单位。其中,每个任务可以在任意(空闲)机器上工作,每个机器的同一时刻只能工作一个任务,每个任务在同一时刻只能被一个机器工作,而且任务做到一半可以打断,拿去其他机器做。问:能否在规定时间内把任务做完。

用一个源点连所有任务,流量是任务需要的天数,每个天数与汇点之间连一条流量是m的边,表示每天只有m台机器工作

用dinic会超时所以用sap

技术分享
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define MAXM 555555
#define MAXN 2222
struct Edge{
    int v,cap,next;
}edge[MAXM];

int pre[MAXN];
int cur[MAXN];
int head[MAXN];
int level[MAXN];
int gap[MAXN];
int n,m;
int NV,NE;
void init(){
    NE = 0;
    memset(head, -1, sizeof(head));
}
int SAP(int vs,int vt){
    memset(pre,-1,sizeof(pre));
    memset(level,0,sizeof(level));
    memset(gap,0,sizeof(gap));
    for(int i=0;i<=NV;i++)cur[i]=head[i];
    int u=pre[vs]=vs,maxflow=0,aug=-1;
    gap[0]=NV;
    while(level[vs]<NV){
loop:
        for(int &i=cur[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(edge[i].cap&&level[u]==level[v]+1){
                aug==-1?aug=edge[i].cap:(aug=min(aug,edge[i].cap));
                pre[v]=u;
                u=v;
                if(v==vt){
                    maxflow+=aug;
                    for(u=pre[u];v!=vs;v=u,u=pre[u]){
                        edge[cur[u]].cap-=aug;
                        edge[cur[u]^1].cap+=aug;
                    }
                    aug=-1;
                }
                goto loop;
            }
        }
        int minlevel=NV;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(edge[i].cap&&minlevel>level[v]){
                cur[u]=i;
                minlevel=level[v];
            }
        }
        gap[level[u]]--;
        if(gap[level[u]]==0)break;
        level[u]=minlevel+1;
        gap[level[u]]++;
        u=pre[u];
    }
    return maxflow;
}

void addedge(int u,int v,int cap,int cc=0){
    //printf("*%d %d %d\n", u, v, cap);
    edge[NE].cap=cap;edge[NE].v=v;
    edge[NE].next=head[u];head[u]=NE++;

    edge[NE].cap=cc;edge[NE].v=u;
    edge[NE].next=head[v];head[v]=NE++;
}


int main(){
    int cas = 1;
    int n, m;
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d%d", &n, &m);
        init();
        int T = 0;
        int sum = 0;
        for(int i = 1; i <= n; i++){                
            int p, s, e;
            scanf("%d%d%d", &p, &s, &e);
            addedge(0, i, p);
            for(int t = s; t <= e; t++){
                addedge(i, t+n, 1);
            }
            T = max(T, e);
            sum += p;
        }

        int src = 0;
        int sink = n+T+1;
        for(int i = 1; i <= T; i++){
            addedge(i+n, sink, m);
        }
        NV = sink+10;                ///注意,比一共有的点数加1
        printf("Case %d: ", cas++);
        int ans = SAP(src, sink);
        //printf("%d\n", ans);
        if(sum == ans)
            printf("Yes\n");
        else
            printf("No\n");
        puts("");
    }
}
View Code

 

网络流小结

标签:

原文地址:http://www.cnblogs.com/icodefive/p/4810613.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!