网络流入门题集合

一直觉得自己图论各种垃圾,而且dinic莫名其妙地各种玄学(虽然每次最后都证明确实要么是建图错了要么是哪儿哪儿错了)
bzoj 1433
这道题其实挺裸的。
源点向每个住校的学生连一条边,每个在校的学生向汇点连一条边,每个住校的学生向可以住的床连一条边(在校生且与他关系好),边的流量都是1.
(感觉自己太垃圾了这道弱智题居然调了好久,而且代码从沈阳码到成都23333)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ms(x,y) memset(x,y,sizeof(x))
using namespace std;

const int N = 100010;
const int oo = 0x73f3f3f;

int t;
int n;
int cnt=0;
int num=1;
int head[N];
int s,tt;
int a[N],b[N];

inline int Min(int a,int b){
    return a<b?a:b;
}

struct node{
    int pre,v,f;
}edge[N];

void addedge(int from,int to,int f){
    num++;
    edge[num].pre=head[from];
    edge[num].v=to;
    edge[num].f=f;
    head[from]=num;
    num++;
    edge[num].pre=head[to];
    edge[num].v=from;
    edge[num].f=0;
    head[to]=num;
}

int dis[N],state[N];
bool vis[N];

bool bfs(){
    int h=0,tail=1;
    state[1]=s;vis[s]=true;
    dis[s]=0;
    do{
        h++;
        int u=state[h];
        for(int i=head[u];i;i=edge[i].pre){
            int v=edge[i].v;
            if(!vis[v]&&edge[i].f){
                tail++;
                state[tail]=v;
                dis[v]=dis[u]+1;
                vis[v]=true;
            }
        }
    }
    while(h<tail);
    if(vis[tt]) return true;
    return false;
}

int dfs(int u,int delta){
    if(u==tt||delta==0) return delta;
    int ans=0;
    for(int i=head[u];i&&delta;i=edge[i].pre){
        int v=edge[i].v;
        if(dis[v]==dis[u]+1&&edge[i].f){
            int dd=dfs(v,Min(delta,edge[i].f));
            edge[i].f-=dd;
            edge[i^1].f+=dd;
            ans+=dd;
            delta-=dd;
            if(!delta) break;
        }
    }
    if(!ans) dis[u]=-1;
    return ans;
}

void zero(){
    ms(state,0);ms(dis,0);ms(vis,0);
}

int Maxflow(){
    int ans=0;
    while(1){
        zero();
        if(!bfs()) break;
        ans+=dfs(s,oo);
    }
    return ans;
}

void update(){
    cnt=0,num=1;ms(a,0);ms(b,0);ms(head,0);
}

int main(){
    scanf("%d",&t);
    while(t--){
        update();       
        scanf("%d",&n);
        s=0,tt=n+n+1;
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            a[i]=x;
            if(x==1) addedge(i+n,tt,1);//如果某个人是在校学生 向汇点连张床 
            else {addedge(s,i,1);cnt++;}//其他非在线学生 源点向其连线 
        }
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            b[i]=x;
            if(a[i]==1&&x==0){//某个人是在校学生 并且留校 
               cnt++;
               addedge(i,n+i,1);//他和自己的床连 
               addedge(s,i,1);}//源点和他自己连 
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                int x;
                scanf("%d",&x);
                if(x==1&&a[i]==0||x==1&&a[i]==1&&b[i]==0){//如果某两个人关系好并且住校 
                      if(a[j]) addedge(i,n+j,1);//他的朋友有床 
                 } 
            }
        }
    //  printf("%d ",cnt);
        if(Maxflow()==cnt) printf("^_^\n");
        else printf("T_T\n");
    }
    return 0;
}

poj 1459
这道题的输入太骚气了233333但其实题还好 随手写了个当前弧优化
【好久以前写的题了当时没有写题解也已经忘了23333】

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define ms(x,y) memset(x,y,sizeof(x))
using namespace std;

const int N = 10010;
const int INF = 1<<30;

int n,np,nc,m;
int tot=1;
int head[N];

inline int Min(int a,int b){
    return a<b?a:b;
}

struct node{
    int pre,v,f;
}edge[N<<1];

void adde(int from,int to,int f){
    tot++;
    edge[tot].pre = head[from];
    edge[tot].v = to;
    edge[tot].f = f;
    head[from] = tot;
    tot++;
    edge[tot].pre = head[to];
    edge[tot].v = from;
    edge[tot].f = 0;
    head[to] = tot;
}

int dep[N],state[N*10];
bool vis[N];
int cur[N];

bool bfs(){
    int h=0,tail=1;
    dep[n]=0;
    state[1]=n;vis[n]=true;
    while(h<tail){
        h++;
        int u=state[h];
        for(int i=head[u];i;i=edge[i].pre){
            int v=edge[i].v;
            if(!vis[v]&&edge[i].f){
               dep[v]=dep[u]+1;
               vis[v]=true;
               tail++;
               state[tail]=v;
            }
        }
    }
    if(vis[n+1]) return true;
    return false;
}

int dfs(int u,int delta){
    if(u==n+1||delta==0) return delta;
    int ans=0;
    for(int &i=cur[u];i&&delta;i=edge[i].pre){
        int v=edge[i].v;
        if(edge[i].f&&dep[v]==dep[u]+1){
            int dd=dfs(v,Min(delta,edge[i].f));
            edge[i].f-=dd;
            edge[i^1].f+=dd;
            delta-=dd;
            ans+=dd;
            if(!delta) break;
        }
    }
    if(!ans) dep[u]=-1;
    return ans;
}

void zero(){
    ms(dep,0);ms(state,0);ms(vis,0);ms(cur,0);
}

int maxflow(){
    int ans=0;
    while(1){
        zero();
        for(register int i=0;i<=n+1;i++) cur[i]=head[i];
        if(!bfs()) break;
        ans+=dfs(n,INF);
    }
    return ans;
}

void update(){
    ms(head,0);ms(edge,0);
    tot=1;
}

int main(){
    while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF){
   //     scanf("%d%d%d%d",&n,&np,&nc,&m);
        update();
        char ch;
        while(m--){
            int u,v,w;
            /*char ch=getchar();
            while(ch!='(')
               ch=getchar(); 
            scanf("%d,%d)%d",&u,&v,&w);//这骚气的输入*/
            cin>>ch>>u>>ch>>v>>ch>>w;
            if(u==v) continue;
            adde(u,v,w);
        }
        for(int i=1;i<=np;i++){
            int u,f;
            /*char ch=getchar();
            while(ch!='(')
               ch=getchar(); 
            scanf("%d)%d",&u,&f);*/
            cin>>ch>>u>>ch>>f;
            adde(n,u,f);
        }
        for(int i=1;i<=nc;i++){
            int u,f;
            /*char ch=getchar();
            while(ch!='(')
               ch=getchar(); 
            scanf("%d)%d",&u,&f);*/
            cin>>ch>>u>>ch>>f;
            adde(u,n+1,f);
        }
        printf("%d\n",maxflow());
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值