模板(网络流判断:是否存在一个一直行列和的矩阵)

来源:互联网 发布:免费进销存 知乎 编辑:程序博客网 时间:2024/06/07 00:55



模版如下://HDU 4888:http://acm.hdu.edu.cn/showproblem.php?pid=4888

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>#include <queue>using namespace std;#define ll __int64#define eps 1e-8const ll Mod=(1e9+7);const int maxn = 510;const int maxm = 50100;int n,m,k;int r[maxn],c[maxn];int ma[maxn][maxn];const int maxnode = 1000 + 5;const int maxedge = 2*161000 + 5;const int oo = 1000000000;int node, src, dest, nedge;int head[maxnode], point[maxedge], next1[maxedge], flow[maxedge], capa[maxedge];//point[x]==y表示第x条边连接y,head,next为邻接表,flow[x]表示x边的动态值,capa[x]表示x边的初始值int dist[maxnode], Q[maxnode], work[maxnode];//dist[i]表示i点的等级void init(int _node, int _src, int _dest){//初始化,node表示点的个数,src表示起点,dest表示终点    node = _node;    src = _src;    dest = _dest;    for (int i = 0; i < node; i++) head[i] = -1;    nedge = 0;}void addedge(int u, int v, int c1, int c2){//增加一条u到v流量为c1,v到u流量为c2的两条边    point[nedge] = v, capa[nedge] = c1, flow[nedge] = 0, next1[nedge] = head[u], head[u] = (nedge++);    point[nedge] = u, capa[nedge] = c2, flow[nedge] = 0, next1[nedge] = head[v], head[v] = (nedge++);}bool dinic_bfs(){    memset(dist, 255, sizeof (dist));    dist[src] = 0;    int sizeQ = 0;    Q[sizeQ++] = src;    for (int cl = 0; cl < sizeQ; cl++)        for (int k = Q[cl], i = head[k]; i >= 0; i = next1[i])            if (flow[i] < capa[i] && dist[point[i]] < 0){                dist[point[i]] = dist[k] + 1;                Q[sizeQ++] = point[i];            }    return dist[dest] >= 0;}int dinic_dfs(int x, int exp){    if (x == dest) return exp;    for (int &i = work[x]; i >= 0; i = next1[i]){        int v = point[i], tmp;        if (flow[i] < capa[i] && dist[v] == dist[x] + 1 && (tmp = dinic_dfs(v, min(exp, capa[i] - flow[i]))) > 0){            flow[i] += tmp;            flow[i^1] -= tmp;            return tmp;        }    }    return 0;}int dinic_flow(){    int result = 0;    while (dinic_bfs()){        for (int i = 0; i < node; i++) work[i] = head[i];        while (1){            int delta = dinic_dfs(src, oo);            if (delta == 0) break;            result += delta;        }    }    return result;}//建图前,运行一遍init();//加边时,运行addedge(a,b,c,0),表示点a到b流量为c的边建成(注意点序号要从0开始)//求解最大流运行dinic_flow(),返回值即为答案bool judge(int sumrow){    int flow = 1;    for(int i = 1;i <= n;i++)        for(int j = n+1;j <= n+m;j ++)            addedge(i,j,k,0);    flow=dinic_flow();    if(flow != sumrow)        return false;    return true;}int main(){   //k为能填原图能填的数字的最大值    while(scanf("%d%d%d",&n,&m,&k) != EOF){        init(n+m+2,0,n+m+1);        int flag = 0;        int sumrow = 0,colrow = 0;        for(int i = 1;i <= n;i++){            scanf("%d",&r[i]);            addedge(0,i,r[i],0);            sumrow += r[i];            if(r[i]<0 || r[i]>m*k)                flag = 1;        }        for(int j = 1;j <= m;j ++){            scanf("%d",&c[j]);            addedge(j+n,n+m+1,c[j],0);            colrow += c[j];            if(c[j]<0 || c[j]>n*k)                flag = 1;        }        if(sumrow != colrow){            printf("Impossible\n");            continue;        }        if(!judge(sumrow))            flag = 1;        if(flag == 1){            printf("Impossible\n");            continue;        }        memset(ma,-1,sizeof(ma));        int i,j;        for(i=1;i<=n;i++)            if(r[i]==0)                for(j=1;j<=m;j++)                    ma[i][j]=0;        for(j=1;j<=m;j++)            if(c[j]==0)                for(i=1;i<=n;i++)                    ma[i][j]=0;        int tt=2;        int sum,num,temp;        while(tt--)        {            for(i=1;i<=n;i++)            {                if(r[i]==0)                {                    for(j=1;j<=m;j++)                        if(ma[i][j]==-1)                            ma[i][j]=0;                    continue;                }                sum=0;                num=0;                for(j=1;j<=m;j++)                {                    if(ma[i][j]==-1)                    {                        num++;                        temp=j;                        sum+=min(k,c[j]);                    }                }                if(num==1)                {                    ma[i][temp]=r[i];                    r[i]-=ma[i][temp];                    c[temp]-=ma[i][temp];                    continue;                }                else if(sum==r[i])                {                    for(j=1;j<=m;j++)                    {                        if(ma[i][j]==-1)                        {                            ma[i][j]=min(k,c[j]);                            r[i]-=ma[i][j];                            c[j]-=ma[i][j];                        }                    }                }            }            for(j=1;j<=m;j++)            {                if(c[j]==0)                {                    for(i=1;i<=n;i++)                        if(ma[i][j]==-1)                            ma[i][j]=0;                    continue;                }                sum=0;                num=0;                for(i=1;i<=n;i++)                {                    if(ma[i][j]==-1)                    {                        num++;                        temp=i;                        sum+=min(k,r[i]);                    }                }                if(num==1)                {                    ma[temp][j]=c[j];                    r[temp]-=ma[temp][j];                    c[j]-=ma[temp][j];                    continue;                }                else if(sum==c[j])                {                    for(i=1;i<=n;i++)                    {                        if(ma[i][j]==-1)                        {                            ma[i][j]=min(k,r[i]);                            r[i]-=ma[i][j];                            c[j]-=ma[i][j];                        }                    }                }            }        }        flag=0;        for(i=1;i<=n;i++)            if(r[i]!=0)            {                flag=1;                break;            }        for(j=1;j<=m;j++)            if(c[j]!=0)            {                flag=1;                break;            }        if(flag==1)            printf("Not Unique\n");        else        {            printf("Unique\n");            for(i=1;i<=n;i++)            {                for(j=1;j<m;j++)                    printf("%d ",ma[i][j]);                printf("%d\n",ma[i][m]);            }        }    }    return 0;}



3 0
原创粉丝点击