hdu4975(二分图)

来源:互联网 发布:win10电脑mac地址修改 编辑:程序博客网 时间:2024/04/30 18:26

链接:点击打开链接

题意:有n行m列矩阵,给出各行的和和各列的和,矩阵元素为0~9,判断是无解,唯一解还是多解

代码:

#include <queue>#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>using namespace std;const int INF=0x3f3f3f3f;struct node{    int u,v,cap;    node(){}    node(int u,int v,int cap):u(u),v(v),cap(cap){}}es[1000005];int R,S,T;int dis[50005],vis[50005],iter[50005];vector<int> tab[50005];vector<int> G[50005];void addedge(int u, int v, int cap){    tab[u].push_back(R);    es[R++]=node(u,v,cap);    tab[v].push_back(R);    es[R++]=node(v,u,0);}int bfs(){    int i,h;    queue<int> q;    q.push(S);    memset(dis,INF,sizeof(dis));    dis[S]=0;    while(q.size()){        h=q.front();        q.pop();        for(i=0;i<tab[h].size();i++){            node &e=es[tab[h][i]];            if(e.cap>0&&dis[e.v]==INF){                dis[e.v]=dis[h]+1;                q.push(e.v);            }        }    }    return dis[T]<INF;}int dfs(int x,int maxflow){    int flow;    if(x==T)    return maxflow;    for(int &i=iter[x];i<tab[x].size();i++){        node &e=es[tab[x][i]];        if(dis[e.v]==dis[x]+1&&e.cap>0){            flow=dfs(e.v,min(maxflow,e.cap));            if(flow){                e.cap-=flow;                es[tab[x][i]^1].cap+=flow;                return flow;            }        }    }    return 0;}int dinic(){    int ans,flow;    ans=0;    while(bfs()){        memset(iter,0,sizeof(iter));        while(flow=dfs(S,INF))        ans+=flow;    }    return ans;}                                               //dinic模板int judge(int s,int t){    int i,tmp;    vis[s]=1;    for(i=0;i<G[s].size();i++){        tmp=G[s][i];        if(tmp==t)                              //防止出现两个节点的环        continue;               if(vis[tmp]==1)        return 1;        if(judge(tmp,s))        return 1;    }    vis[s]=0;    return 0;}int main(){    int N,M,i,j,l,r,t,ans,cas,num,sign;    cas=1;    scanf("%d",&t);    while(t--){                                 //以行和列建立二分图跑网络流        scanf("%d%d",&N,&M);        l=r=0;        S=0,R=0,T=N+M+1;        for(i=0;i<=T;i++){        G[i].clear();        tab[i].clear();        }        memset(vis,0,sizeof(vis));        for(i=1;i<=N;i++){            scanf("%d",&num);            addedge(S,i,num);            l+=num;        }        for(i=1;i<=M;i++){            scanf("%d",&num);            addedge(i+N,T,num);            r+=num;        }        for(i=1;i<=N;i++)        for(j=1;j<=M;j++)        addedge(i,j+N,9);                       //因为只能0~9所以容量建为9        if(l!=r){                               //如果行的和和列的和不相等则一定无解            printf("Case #%d: So naive!\n",cas++);            continue;        }        ans=dinic();        if(ans!=l){                             //不是满流的也无解            printf("Case #%d: So naive!\n",cas++);            continue;        }        for(i=0;i<R;i++)        if(es[i].cap>0)                         //将残余网络保存下来判断是否有环,从而        G[es[i].u].push_back(es[i].v);          //确定是否有多组解,因为当残余网络中有        sign=0;                                 //环时则可以通过残余网络去跑一些原来的流量        for(i=1;i<=N;i++)        if(judge(i,-1)){            sign=1;            break;        }        if(sign)        printf("Case #%d: So young!\n",cas++);        else        printf("Case #%d: So simple!\n",cas++);    }    return 0;}


 

0 0
原创粉丝点击